]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.25 2001/02/20 07:03:17 jgg Exp $
4 /* ######################################################################
8 This is a skeleton class that implements most of the functionality
9 of a method and some useful 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 %s\n",Queue
->Uri
.c_str(),Err
.c_str(),
104 FetchItem
*Tmp
= Queue
;
107 if (Tmp
== QueueBack
)
111 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
112 "Message: %s %s\n",Err
.c_str(),
115 // Set the transient flag
116 if (Transient
== true)
117 strcat(S
,"Transient-Failure: true\n\n");
121 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
125 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
126 // ---------------------------------------------------------------------
128 void pkgAcqMethod::URIStart(FetchResult
&Res
)
136 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
138 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Size: %lu\n",Res
.Size
);
140 if (Res
.LastModified
!= 0)
141 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Last-Modified: %s\n",
142 TimeRFC1123(Res
.LastModified
).c_str());
144 if (Res
.ResumePoint
!= 0)
145 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Resume-Point: %lu\n",
149 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
153 // AcqMethod::URIDone - A URI is finished /*{{{*/
154 // ---------------------------------------------------------------------
156 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
164 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
166 if (Res
.Filename
.empty() == false)
167 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
170 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Size: %lu\n",Res
.Size
);
172 if (Res
.LastModified
!= 0)
173 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Last-Modified: %s\n",
174 TimeRFC1123(Res
.LastModified
).c_str());
176 if (Res
.MD5Sum
.empty() == false)
177 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
179 if (Res
.ResumePoint
!= 0)
180 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Resume-Point: %lu\n",
183 if (Res
.IMSHit
== true)
184 strcat(End
,"IMS-Hit: true\n");
189 if (Alt
->Filename
.empty() == false)
190 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
193 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
195 if (Alt
->LastModified
!= 0)
196 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Last-Modified: %s\n",
197 TimeRFC1123(Alt
->LastModified
).c_str());
199 if (Alt
->MD5Sum
.empty() == false)
200 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-MD5-Hash: %s\n",
201 Alt
->MD5Sum
.c_str());
203 if (Alt
->IMSHit
== true)
204 strcat(End
,"Alt-IMS-Hit: true\n");
208 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
212 FetchItem
*Tmp
= Queue
;
215 if (Tmp
== QueueBack
)
219 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
220 // ---------------------------------------------------------------------
221 /* This sends a 403 Media Failure message to the APT and waits for it
223 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
226 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
227 Required
.c_str(),Drive
.c_str());
229 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
232 vector
<string
> MyMessages
;
234 /* Here we read messages until we find a 603, each non 603 message is
235 appended to the main message list for later processing */
238 if (WaitFd(STDIN_FILENO
) == false)
241 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
244 string Message
= MyMessages
.front();
245 MyMessages
.erase(MyMessages
.begin());
247 // Fetch the message number
249 int Number
= strtol(Message
.c_str(),&End
,10);
250 if (End
== Message
.c_str())
252 cerr
<< "Malformed message!" << endl
;
259 while (MyMessages
.empty() == false)
261 Messages
.push_back(MyMessages
.front());
262 MyMessages
.erase(MyMessages
.begin());
265 return !StringToBool(LookupTag(Message
,"Fail"),false);
268 Messages
.push_back(Message
);
272 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
273 // ---------------------------------------------------------------------
274 /* This parses each configuration entry and puts it into the _config
275 Configuration class. */
276 bool pkgAcqMethod::Configuration(string Message
)
278 ::Configuration
&Cnf
= *_config
;
280 const char *I
= Message
.begin();
282 unsigned int Length
= strlen("Config-Item");
283 for (; I
+ Length
< Message
.end(); I
++)
286 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
291 for (; I
< Message
.end() && *I
== ' '; I
++);
292 const char *Equals
= I
;
293 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
294 const char *End
= Equals
;
295 for (; End
< Message
.end() && *End
!= '\n'; End
++);
299 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
300 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
307 // AcqMethod::Run - Run the message engine /*{{{*/
308 // ---------------------------------------------------------------------
309 /* Fetch any messages and execute them. In single mode it returns 1 if
310 there are no more available messages - any other result is a
311 fatal failure code! */
312 int pkgAcqMethod::Run(bool Single
)
316 // Block if the message queue is empty
317 if (Messages
.empty() == true)
320 if (WaitFd(STDIN_FILENO
) == false)
322 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
326 // Single mode exits if the message queue is empty
327 if (Single
== true && Messages
.empty() == true)
330 string Message
= Messages
.front();
331 Messages
.erase(Messages
.begin());
333 // Fetch the message number
335 int Number
= strtol(Message
.c_str(),&End
,10);
336 if (End
== Message
.c_str())
338 cerr
<< "Malformed message!" << endl
;
345 if (Configuration(Message
) == false)
351 FetchItem
*Tmp
= new FetchItem
;
353 Tmp
->Uri
= LookupTag(Message
,"URI");
354 Tmp
->DestFile
= LookupTag(Message
,"FileName");
355 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
356 Tmp
->LastModified
= 0;
357 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
360 // Append it to the list
361 FetchItem
**I
= &Queue
;
362 for (; *I
!= 0; I
= &(*I
)->Next
);
367 // Notify that this item is to be fetched.
368 if (Fetch(Tmp
) == false)
380 // AcqMethod::Log - Send a log message /*{{{*/
381 // ---------------------------------------------------------------------
383 void pkgAcqMethod::Log(const char *Format
,...)
385 string CurrentURI
= "<UNKNOWN>";
387 CurrentURI
= Queue
->Uri
;
390 va_start(args
,Format
);
392 // sprintf the description
394 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n"
395 "Message: ",CurrentURI
.c_str());
397 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
400 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
404 // AcqMethod::Status - Send a status message /*{{{*/
405 // ---------------------------------------------------------------------
407 void pkgAcqMethod::Status(const char *Format
,...)
409 string CurrentURI
= "<UNKNOWN>";
411 CurrentURI
= Queue
->Uri
;
414 va_start(args
,Format
);
416 // sprintf the description
418 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n"
419 "Message: ",CurrentURI
.c_str());
421 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
424 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
429 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
430 // ---------------------------------------------------------------------
432 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
433 IMSHit(false), Size(0), ResumePoint(0)