]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.27 2001/05/22 04:27:11 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>
26 #include <apt-pkg/hashes.h>
36 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
37 // ---------------------------------------------------------------------
38 /* This constructs the initialization text */
39 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
43 strcat(End
,"100 Capabilities\n");
44 sprintf(End
+strlen(End
),"Version: %s\n",Ver
);
46 if ((Flags
& SingleInstance
) == SingleInstance
)
47 strcat(End
,"Single-Instance: true\n");
49 if ((Flags
& Pipeline
) == Pipeline
)
50 strcat(End
,"Pipeline: true\n");
52 if ((Flags
& SendConfig
) == SendConfig
)
53 strcat(End
,"Send-Config: true\n");
55 if ((Flags
& LocalOnly
) == LocalOnly
)
56 strcat(End
,"Local-Only: true\n");
58 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
59 strcat(End
,"Needs-Cleanup: true\n");
61 if ((Flags
& Removable
) == Removable
)
62 strcat(End
,"Removable: true\n");
65 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
68 SetNonBlock(STDIN_FILENO
,true);
74 // AcqMethod::Fail - A fetch has failed /*{{{*/
75 // ---------------------------------------------------------------------
77 void pkgAcqMethod::Fail(bool Transient
)
79 string Err
= "Undetermined Error";
80 if (_error
->empty() == false)
81 _error
->PopMessage(Err
);
86 // AcqMethod::Fail - A fetch has failed /*{{{*/
87 // ---------------------------------------------------------------------
89 void pkgAcqMethod::Fail(string Err
,bool Transient
)
91 // Strip out junk from the error messages
92 for (string::iterator I
= Err
.begin(); I
!= Err
.end(); I
++)
103 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: %s\n"
104 "Message: %s %s\n",Queue
->Uri
.c_str(),Err
.c_str(),
108 FetchItem
*Tmp
= Queue
;
111 if (Tmp
== QueueBack
)
115 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
116 "Message: %s %s\n",Err
.c_str(),
119 // Set the transient flag
120 if (Transient
== true)
121 strcat(S
,"Transient-Failure: true\n\n");
125 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
129 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
130 // ---------------------------------------------------------------------
132 void pkgAcqMethod::URIStart(FetchResult
&Res
)
140 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
142 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Size: %lu\n",Res
.Size
);
144 if (Res
.LastModified
!= 0)
145 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Last-Modified: %s\n",
146 TimeRFC1123(Res
.LastModified
).c_str());
148 if (Res
.ResumePoint
!= 0)
149 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Resume-Point: %lu\n",
153 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
157 // AcqMethod::URIDone - A URI is finished /*{{{*/
158 // ---------------------------------------------------------------------
160 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
168 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
170 if (Res
.Filename
.empty() == false)
171 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
174 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Size: %lu\n",Res
.Size
);
176 if (Res
.LastModified
!= 0)
177 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Last-Modified: %s\n",
178 TimeRFC1123(Res
.LastModified
).c_str());
180 if (Res
.MD5Sum
.empty() == false)
181 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
182 if (Res
.SHA1Sum
.empty() == false)
183 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"SHA1-Hash: %s\n",Res
.SHA1Sum
.c_str());
185 if (Res
.ResumePoint
!= 0)
186 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Resume-Point: %lu\n",
189 if (Res
.IMSHit
== true)
190 strcat(End
,"IMS-Hit: true\n");
195 if (Alt
->Filename
.empty() == false)
196 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
199 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
201 if (Alt
->LastModified
!= 0)
202 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Last-Modified: %s\n",
203 TimeRFC1123(Alt
->LastModified
).c_str());
205 if (Alt
->MD5Sum
.empty() == false)
206 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-MD5-Hash: %s\n",
207 Alt
->MD5Sum
.c_str());
208 if (Alt
->SHA1Sum
.empty() == false)
209 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-SHA1-Hash: %s\n",
210 Alt
->SHA1Sum
.c_str());
212 if (Alt
->IMSHit
== true)
213 strcat(End
,"Alt-IMS-Hit: true\n");
217 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
221 FetchItem
*Tmp
= Queue
;
224 if (Tmp
== QueueBack
)
228 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
229 // ---------------------------------------------------------------------
230 /* This sends a 403 Media Failure message to the APT and waits for it
232 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
235 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
236 Required
.c_str(),Drive
.c_str());
238 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
241 vector
<string
> MyMessages
;
243 /* Here we read messages until we find a 603, each non 603 message is
244 appended to the main message list for later processing */
247 if (WaitFd(STDIN_FILENO
) == false)
250 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
253 string Message
= MyMessages
.front();
254 MyMessages
.erase(MyMessages
.begin());
256 // Fetch the message number
258 int Number
= strtol(Message
.c_str(),&End
,10);
259 if (End
== Message
.c_str())
261 cerr
<< "Malformed message!" << endl
;
268 while (MyMessages
.empty() == false)
270 Messages
.push_back(MyMessages
.front());
271 MyMessages
.erase(MyMessages
.begin());
274 return !StringToBool(LookupTag(Message
,"Fail"),false);
277 Messages
.push_back(Message
);
281 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
282 // ---------------------------------------------------------------------
283 /* This parses each configuration entry and puts it into the _config
284 Configuration class. */
285 bool pkgAcqMethod::Configuration(string Message
)
287 ::Configuration
&Cnf
= *_config
;
289 const char *I
= Message
.c_str();
290 const char *MsgEnd
= I
+ Message
.length();
292 unsigned int Length
= strlen("Config-Item");
293 for (; I
+ Length
< MsgEnd
; I
++)
296 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
301 for (; I
< MsgEnd
&& *I
== ' '; I
++);
302 const char *Equals
= I
;
303 for (; Equals
< MsgEnd
&& *Equals
!= '='; Equals
++);
304 const char *End
= Equals
;
305 for (; End
< MsgEnd
&& *End
!= '\n'; End
++);
309 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
310 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
317 // AcqMethod::Run - Run the message engine /*{{{*/
318 // ---------------------------------------------------------------------
319 /* Fetch any messages and execute them. In single mode it returns 1 if
320 there are no more available messages - any other result is a
321 fatal failure code! */
322 int pkgAcqMethod::Run(bool Single
)
326 // Block if the message queue is empty
327 if (Messages
.empty() == true)
330 if (WaitFd(STDIN_FILENO
) == false)
332 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
336 // Single mode exits if the message queue is empty
337 if (Single
== true && Messages
.empty() == true)
340 string Message
= Messages
.front();
341 Messages
.erase(Messages
.begin());
343 // Fetch the message number
345 int Number
= strtol(Message
.c_str(),&End
,10);
346 if (End
== Message
.c_str())
348 cerr
<< "Malformed message!" << endl
;
355 if (Configuration(Message
) == false)
361 FetchItem
*Tmp
= new FetchItem
;
363 Tmp
->Uri
= LookupTag(Message
,"URI");
364 Tmp
->DestFile
= LookupTag(Message
,"FileName");
365 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
366 Tmp
->LastModified
= 0;
367 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
370 // Append it to the list
371 FetchItem
**I
= &Queue
;
372 for (; *I
!= 0; I
= &(*I
)->Next
);
377 // Notify that this item is to be fetched.
378 if (Fetch(Tmp
) == false)
390 // AcqMethod::Log - Send a log message /*{{{*/
391 // ---------------------------------------------------------------------
393 void pkgAcqMethod::Log(const char *Format
,...)
395 string CurrentURI
= "<UNKNOWN>";
397 CurrentURI
= Queue
->Uri
;
400 va_start(args
,Format
);
402 // sprintf the description
404 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n"
405 "Message: ",CurrentURI
.c_str());
407 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
410 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
414 // AcqMethod::Status - Send a status message /*{{{*/
415 // ---------------------------------------------------------------------
417 void pkgAcqMethod::Status(const char *Format
,...)
419 string CurrentURI
= "<UNKNOWN>";
421 CurrentURI
= Queue
->Uri
;
424 va_start(args
,Format
);
426 // sprintf the description
428 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n"
429 "Message: ",CurrentURI
.c_str());
431 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
434 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
439 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
440 // ---------------------------------------------------------------------
442 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
443 IMSHit(false), Size(0), ResumePoint(0)
447 // AcqMethod::FetchResult::TakeHashes - Load hashes /*{{{*/
448 // ---------------------------------------------------------------------
449 /* This hides the number of hashes we are supporting from the caller.
450 It just deals with the hash class. */
451 void pkgAcqMethod::FetchResult::TakeHashes(Hashes
&Hash
)
453 MD5Sum
= Hash
.MD5
.Result();
454 SHA1Sum
= Hash
.SHA1
.Result();