]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.21 1999/10/18 00:37:35 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");
53 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
54 strcat(End
,"Needs-Cleanup: true\n");
57 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
60 SetNonBlock(STDIN_FILENO
,true);
66 // AcqMethod::Fail - A fetch has failed /*{{{*/
67 // ---------------------------------------------------------------------
69 void pkgAcqMethod::Fail(bool Transient
)
71 string Err
= "Undetermined Error";
72 if (_error
->empty() == false)
73 _error
->PopMessage(Err
);
78 // AcqMethod::Fail - A fetch has failed /*{{{*/
79 // ---------------------------------------------------------------------
81 void pkgAcqMethod::Fail(string Err
,bool Transient
)
83 // Strip out junk from the error messages
84 for (char *I
= Err
.begin(); I
!= Err
.end(); I
++)
95 snprintf(S
,sizeof(S
),"400 URI Failure\nURI: %s\n"
96 "Message: %s\n",Queue
->Uri
.c_str(),Err
.c_str());
99 FetchItem
*Tmp
= Queue
;
102 if (Tmp
== QueueBack
)
106 snprintf(S
,sizeof(S
),"400 URI Failure\nURI: <UNKNOWN>\n"
107 "Message: %s\n",Err
.c_str());
109 // Set the transient flag
110 if (Transient
== true)
111 strcat(S
,"Transient-Failure: true\n\n");
115 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
119 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
120 // ---------------------------------------------------------------------
122 void pkgAcqMethod::URIStart(FetchResult
&Res
)
130 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
132 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Size: %lu\n",Res
.Size
);
134 if (Res
.LastModified
!= 0)
135 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Last-Modified: %s\n",
136 TimeRFC1123(Res
.LastModified
).c_str());
138 if (Res
.ResumePoint
!= 0)
139 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Resume-Point: %lu\n",
143 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
147 // AcqMethod::URIDone - A URI is finished /*{{{*/
148 // ---------------------------------------------------------------------
150 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
158 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
160 if (Res
.Filename
.empty() == false)
161 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
164 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Size: %lu\n",Res
.Size
);
166 if (Res
.LastModified
!= 0)
167 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Last-Modified: %s\n",
168 TimeRFC1123(Res
.LastModified
).c_str());
170 if (Res
.MD5Sum
.empty() == false)
171 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
173 if (Res
.ResumePoint
!= 0)
174 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Resume-Point: %lu\n",
177 if (Res
.IMSHit
== true)
178 strcat(End
,"IMS-Hit: true\n");
183 if (Alt
->Filename
.empty() == false)
184 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
187 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
189 if (Alt
->LastModified
!= 0)
190 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-Last-Modified: %s\n",
191 TimeRFC1123(Alt
->LastModified
).c_str());
193 if (Alt
->MD5Sum
.empty() == false)
194 End
+= snprintf(End
,sizeof(S
) - (End
- S
),"Alt-MD5-Hash: %s\n",
195 Alt
->MD5Sum
.c_str());
197 if (Alt
->IMSHit
== true)
198 strcat(End
,"Alt-IMS-Hit: true\n");
202 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
206 FetchItem
*Tmp
= Queue
;
209 if (Tmp
== QueueBack
)
213 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
214 // ---------------------------------------------------------------------
215 /* This sends a 403 Media Failure message to the APT and waits for it
217 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
220 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
221 Required
.c_str(),Drive
.c_str());
223 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
226 vector
<string
> MyMessages
;
228 /* Here we read messages until we find a 603, each non 603 message is
229 appended to the main message list for later processing */
232 if (WaitFd(STDIN_FILENO
) == false)
235 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
238 string Message
= MyMessages
.front();
239 MyMessages
.erase(MyMessages
.begin());
241 // Fetch the message number
243 int Number
= strtol(Message
.c_str(),&End
,10);
244 if (End
== Message
.c_str())
246 cerr
<< "Malformed message!" << endl
;
253 while (MyMessages
.empty() == false)
255 Messages
.push_back(MyMessages
.front());
256 MyMessages
.erase(MyMessages
.begin());
259 return !StringToBool(LookupTag(Message
,"Fail"),false);
262 Messages
.push_back(Message
);
266 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
267 // ---------------------------------------------------------------------
268 /* This parses each configuration entry and puts it into the _config
269 Configuration class. */
270 bool pkgAcqMethod::Configuration(string Message
)
272 ::Configuration
&Cnf
= *_config
;
274 const char *I
= Message
.begin();
276 unsigned int Length
= strlen("Config-Item");
277 for (; I
+ Length
< Message
.end(); I
++)
280 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
285 for (; I
< Message
.end() && *I
== ' '; I
++);
286 const char *Equals
= I
;
287 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
288 const char *End
= Equals
;
289 for (; End
< Message
.end() && *End
!= '\n'; End
++);
293 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
294 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
301 // AcqMethod::Run - Run the message engine /*{{{*/
302 // ---------------------------------------------------------------------
303 /* Fetch any messages and execute them. In single mode it returns 1 if
304 there are no more available messages - any other result is a
305 fatal failure code! */
306 int pkgAcqMethod::Run(bool Single
)
310 // Block if the message queue is empty
311 if (Messages
.empty() == true)
314 if (WaitFd(STDIN_FILENO
) == false)
316 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
320 // Single mode exits if the message queue is empty
321 if (Single
== true && Messages
.empty() == true)
324 string Message
= Messages
.front();
325 Messages
.erase(Messages
.begin());
327 // Fetch the message number
329 int Number
= strtol(Message
.c_str(),&End
,10);
330 if (End
== Message
.c_str())
332 cerr
<< "Malformed message!" << endl
;
339 if (Configuration(Message
) == false)
345 FetchItem
*Tmp
= new FetchItem
;
347 Tmp
->Uri
= LookupTag(Message
,"URI");
348 Tmp
->DestFile
= LookupTag(Message
,"FileName");
349 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
350 Tmp
->LastModified
= 0;
351 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
354 // Append it to the list
355 FetchItem
**I
= &Queue
;
356 for (; *I
!= 0; I
= &(*I
)->Next
);
361 // Notify that this item is to be fetched.
362 if (Fetch(Tmp
) == false)
374 // AcqMethod::Log - Send a log message /*{{{*/
375 // ---------------------------------------------------------------------
377 void pkgAcqMethod::Log(const char *Format
,...)
379 string CurrentURI
= "<UNKNOWN>";
381 CurrentURI
= Queue
->Uri
;
384 va_start(args
,Format
);
386 // sprintf the description
388 unsigned int Len
= snprintf(S
,sizeof(S
),"101 Log\nURI: %s\n"
389 "Message: ",CurrentURI
.c_str());
391 vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
);
394 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
398 // AcqMethod::Status - Send a status message /*{{{*/
399 // ---------------------------------------------------------------------
401 void pkgAcqMethod::Status(const char *Format
,...)
403 string CurrentURI
= "<UNKNOWN>";
405 CurrentURI
= Queue
->Uri
;
408 va_start(args
,Format
);
410 // sprintf the description
412 unsigned int Len
= snprintf(S
,sizeof(S
),"102 Status\nURI: %s\n"
413 "Message: ",CurrentURI
.c_str());
415 vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
);
418 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
423 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
424 // ---------------------------------------------------------------------
426 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
427 IMSHit(false), Size(0), ResumePoint(0)