]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.20 1999/08/04 02:39:13 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>
31 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
32 // ---------------------------------------------------------------------
33 /* This constructs the initialization text */
34 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
38 strcat(End
,"100 Capabilities\n");
39 sprintf(End
+strlen(End
),"Version: %s\n",Ver
);
41 if ((Flags
& SingleInstance
) == SingleInstance
)
42 strcat(End
,"Single-Instance: true\n");
44 if ((Flags
& Pipeline
) == Pipeline
)
45 strcat(End
,"Pipeline: true\n");
47 if ((Flags
& SendConfig
) == SendConfig
)
48 strcat(End
,"Send-Config: true\n");
50 if ((Flags
& LocalOnly
) == LocalOnly
)
51 strcat(End
,"Local-Only: true\n");
54 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
57 SetNonBlock(STDIN_FILENO
,true);
63 // AcqMethod::Fail - A fetch has failed /*{{{*/
64 // ---------------------------------------------------------------------
66 void pkgAcqMethod::Fail(bool Transient
)
68 string Err
= "Undetermined Error";
69 if (_error
->empty() == false)
70 _error
->PopMessage(Err
);
75 // AcqMethod::Fail - A fetch has failed /*{{{*/
76 // ---------------------------------------------------------------------
78 void pkgAcqMethod::Fail(string Err
,bool Transient
)
80 // Strip out junk from the error messages
81 for (char *I
= Err
.begin(); I
!= Err
.end(); I
++)
92 snprintf(S
,sizeof(S
),"400 URI Failure\nURI: %s\n"
93 "Message: %s\n",Queue
->Uri
.c_str(),Err
.c_str());
96 FetchItem
*Tmp
= Queue
;
103 snprintf(S
,sizeof(S
),"400 URI Failure\nURI: <UNKNOWN>\n"
104 "Message: %s\n",Err
.c_str());
106 // Set the transient flag
107 if (Transient
== true)
108 strcat(S
,"Transient-Failure: true\n\n");
112 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
116 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
117 // ---------------------------------------------------------------------
119 void pkgAcqMethod::URIStart(FetchResult
&Res
)
127 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
129 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Size: %lu\n",Res
.Size
);
131 if (Res
.LastModified
!= 0)
132 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Last-Modified: %s\n",
133 TimeRFC1123(Res
.LastModified
).c_str());
135 if (Res
.ResumePoint
!= 0)
136 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Resume-Point: %lu\n",
140 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
144 // AcqMethod::URIDone - A URI is finished /*{{{*/
145 // ---------------------------------------------------------------------
147 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
155 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
157 if (Res
.Filename
.empty() == false)
158 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
161 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Size: %lu\n",Res
.Size
);
163 if (Res
.LastModified
!= 0)
164 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Last-Modified: %s\n",
165 TimeRFC1123(Res
.LastModified
).c_str());
167 if (Res
.MD5Sum
.empty() == false)
168 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
170 if (Res
.ResumePoint
!= 0)
171 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Resume-Point: %lu\n",
174 if (Res
.IMSHit
== true)
175 strcat(End
,"IMS-Hit: true\n");
180 if (Alt
->Filename
.empty() == false)
181 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
184 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
186 if (Alt
->LastModified
!= 0)
187 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Last-Modified: %s\n",
188 TimeRFC1123(Alt
->LastModified
).c_str());
190 if (Alt
->MD5Sum
.empty() == false)
191 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-MD5-Hash: %s\n",
192 Alt
->MD5Sum
.c_str());
194 if (Alt
->IMSHit
== true)
195 strcat(End
,"Alt-IMS-Hit: true\n");
199 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
203 FetchItem
*Tmp
= Queue
;
206 if (Tmp
== QueueBack
)
210 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
211 // ---------------------------------------------------------------------
212 /* This sends a 403 Media Failure message to the APT and waits for it
214 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
217 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
218 Required
.c_str(),Drive
.c_str());
220 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
223 vector
<string
> MyMessages
;
225 /* Here we read messages until we find a 603, each non 603 message is
226 appended to the main message list for later processing */
229 if (WaitFd(STDIN_FILENO
) == false)
232 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
235 string Message
= MyMessages
.front();
236 MyMessages
.erase(MyMessages
.begin());
238 // Fetch the message number
240 int Number
= strtol(Message
.c_str(),&End
,10);
241 if (End
== Message
.c_str())
243 cerr
<< "Malformed message!" << endl
;
250 while (MyMessages
.empty() == false)
252 Messages
.push_back(MyMessages
.front());
253 MyMessages
.erase(MyMessages
.begin());
256 return !StringToBool(LookupTag(Message
,"Fail"),false);
259 Messages
.push_back(Message
);
263 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
264 // ---------------------------------------------------------------------
265 /* This parses each configuration entry and puts it into the _config
266 Configuration class. */
267 bool pkgAcqMethod::Configuration(string Message
)
269 ::Configuration
&Cnf
= *_config
;
271 const char *I
= Message
.begin();
273 unsigned int Length
= strlen("Config-Item");
274 for (; I
+ Length
< Message
.end(); I
++)
277 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
282 for (; I
< Message
.end() && *I
== ' '; I
++);
283 const char *Equals
= I
;
284 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
285 const char *End
= Equals
;
286 for (; End
< Message
.end() && *End
!= '\n'; End
++);
290 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
291 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
298 // AcqMethod::Run - Run the message engine /*{{{*/
299 // ---------------------------------------------------------------------
300 /* Fetch any messages and execute them. In single mode it returns 1 if
301 there are no more available messages - any other result is a
302 fatal failure code! */
303 int pkgAcqMethod::Run(bool Single
)
307 // Block if the message queue is empty
308 if (Messages
.empty() == true)
311 if (WaitFd(STDIN_FILENO
) == false)
314 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
318 // Single mode exits if the message queue is empty
319 if (Single
== true && Messages
.empty() == true)
322 string Message
= Messages
.front();
323 Messages
.erase(Messages
.begin());
325 // Fetch the message number
327 int Number
= strtol(Message
.c_str(),&End
,10);
328 if (End
== Message
.c_str())
330 cerr
<< "Malformed message!" << endl
;
337 if (Configuration(Message
) == false)
343 FetchItem
*Tmp
= new FetchItem
;
345 Tmp
->Uri
= LookupTag(Message
,"URI");
346 Tmp
->DestFile
= LookupTag(Message
,"FileName");
347 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
348 Tmp
->LastModified
= 0;
349 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
352 // Append it to the list
353 FetchItem
**I
= &Queue
;
354 for (; *I
!= 0; I
= &(*I
)->Next
);
359 // Notify that this item is to be fetched.
360 if (Fetch(Tmp
) == false)
371 // AcqMethod::Log - Send a log message /*{{{*/
372 // ---------------------------------------------------------------------
374 void pkgAcqMethod::Log(const char *Format
,...)
376 string CurrentURI
= "<UNKNOWN>";
378 CurrentURI
= Queue
->Uri
;
381 va_start(args
,Format
);
383 // sprintf the description
385 unsigned int Len
= snprintf(S
,sizeof(S
),"101 Log\nURI: %s\n"
386 "Message: ",CurrentURI
.c_str());
388 vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
);
391 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
395 // AcqMethod::Status - Send a status message /*{{{*/
396 // ---------------------------------------------------------------------
398 void pkgAcqMethod::Status(const char *Format
,...)
400 string CurrentURI
= "<UNKNOWN>";
402 CurrentURI
= Queue
->Uri
;
405 va_start(args
,Format
);
407 // sprintf the description
409 unsigned int Len
= snprintf(S
,sizeof(S
),"102 Status\nURI: %s\n"
410 "Message: ",CurrentURI
.c_str());
412 vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
);
415 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
420 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
421 // ---------------------------------------------------------------------
423 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
424 IMSHit(false), Size(0), ResumePoint(0)