]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.26 2001/03/13 06:51:46 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>
33 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
34 // ---------------------------------------------------------------------
35 /* This constructs the initialization text */
36 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
40 strcat(End
,"100 Capabilities\n");
41 sprintf(End
+strlen(End
),"Version: %s\n",Ver
);
43 if ((Flags
& SingleInstance
) == SingleInstance
)
44 strcat(End
,"Single-Instance: true\n");
46 if ((Flags
& Pipeline
) == Pipeline
)
47 strcat(End
,"Pipeline: true\n");
49 if ((Flags
& SendConfig
) == SendConfig
)
50 strcat(End
,"Send-Config: true\n");
52 if ((Flags
& LocalOnly
) == LocalOnly
)
53 strcat(End
,"Local-Only: true\n");
55 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
56 strcat(End
,"Needs-Cleanup: true\n");
58 if ((Flags
& Removable
) == Removable
)
59 strcat(End
,"Removable: true\n");
62 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
65 SetNonBlock(STDIN_FILENO
,true);
71 // AcqMethod::Fail - A fetch has failed /*{{{*/
72 // ---------------------------------------------------------------------
74 void pkgAcqMethod::Fail(bool Transient
)
76 string Err
= "Undetermined Error";
77 if (_error
->empty() == false)
78 _error
->PopMessage(Err
);
83 // AcqMethod::Fail - A fetch has failed /*{{{*/
84 // ---------------------------------------------------------------------
86 void pkgAcqMethod::Fail(string Err
,bool Transient
)
88 // Strip out junk from the error messages
89 for (char *I
= Err
.begin(); I
!= Err
.end(); I
++)
100 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: %s\n"
101 "Message: %s %s\n",Queue
->Uri
.c_str(),Err
.c_str(),
105 FetchItem
*Tmp
= Queue
;
108 if (Tmp
== QueueBack
)
112 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
113 "Message: %s %s\n",Err
.c_str(),
116 // Set the transient flag
117 if (Transient
== true)
118 strcat(S
,"Transient-Failure: true\n\n");
122 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
126 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
127 // ---------------------------------------------------------------------
129 void pkgAcqMethod::URIStart(FetchResult
&Res
)
137 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
139 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Size: %lu\n",Res
.Size
);
141 if (Res
.LastModified
!= 0)
142 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Last-Modified: %s\n",
143 TimeRFC1123(Res
.LastModified
).c_str());
145 if (Res
.ResumePoint
!= 0)
146 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Resume-Point: %lu\n",
150 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
154 // AcqMethod::URIDone - A URI is finished /*{{{*/
155 // ---------------------------------------------------------------------
157 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
165 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
167 if (Res
.Filename
.empty() == false)
168 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
171 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Size: %lu\n",Res
.Size
);
173 if (Res
.LastModified
!= 0)
174 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Last-Modified: %s\n",
175 TimeRFC1123(Res
.LastModified
).c_str());
177 if (Res
.MD5Sum
.empty() == false)
178 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
179 if (Res
.SHA1Sum
.empty() == false)
180 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"SHA1-Hash: %s\n",Res
.SHA1Sum
.c_str());
182 if (Res
.ResumePoint
!= 0)
183 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Resume-Point: %lu\n",
186 if (Res
.IMSHit
== true)
187 strcat(End
,"IMS-Hit: true\n");
192 if (Alt
->Filename
.empty() == false)
193 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
196 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
198 if (Alt
->LastModified
!= 0)
199 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Last-Modified: %s\n",
200 TimeRFC1123(Alt
->LastModified
).c_str());
202 if (Alt
->MD5Sum
.empty() == false)
203 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-MD5-Hash: %s\n",
204 Alt
->MD5Sum
.c_str());
205 if (Alt
->SHA1Sum
.empty() == false)
206 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-SHA1-Hash: %s\n",
207 Alt
->SHA1Sum
.c_str());
209 if (Alt
->IMSHit
== true)
210 strcat(End
,"Alt-IMS-Hit: true\n");
214 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
218 FetchItem
*Tmp
= Queue
;
221 if (Tmp
== QueueBack
)
225 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
226 // ---------------------------------------------------------------------
227 /* This sends a 403 Media Failure message to the APT and waits for it
229 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
232 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
233 Required
.c_str(),Drive
.c_str());
235 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
238 vector
<string
> MyMessages
;
240 /* Here we read messages until we find a 603, each non 603 message is
241 appended to the main message list for later processing */
244 if (WaitFd(STDIN_FILENO
) == false)
247 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
250 string Message
= MyMessages
.front();
251 MyMessages
.erase(MyMessages
.begin());
253 // Fetch the message number
255 int Number
= strtol(Message
.c_str(),&End
,10);
256 if (End
== Message
.c_str())
258 cerr
<< "Malformed message!" << endl
;
265 while (MyMessages
.empty() == false)
267 Messages
.push_back(MyMessages
.front());
268 MyMessages
.erase(MyMessages
.begin());
271 return !StringToBool(LookupTag(Message
,"Fail"),false);
274 Messages
.push_back(Message
);
278 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
279 // ---------------------------------------------------------------------
280 /* This parses each configuration entry and puts it into the _config
281 Configuration class. */
282 bool pkgAcqMethod::Configuration(string Message
)
284 ::Configuration
&Cnf
= *_config
;
286 const char *I
= Message
.begin();
288 unsigned int Length
= strlen("Config-Item");
289 for (; I
+ Length
< Message
.end(); I
++)
292 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
297 for (; I
< Message
.end() && *I
== ' '; I
++);
298 const char *Equals
= I
;
299 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
300 const char *End
= Equals
;
301 for (; End
< Message
.end() && *End
!= '\n'; End
++);
305 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
306 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
313 // AcqMethod::Run - Run the message engine /*{{{*/
314 // ---------------------------------------------------------------------
315 /* Fetch any messages and execute them. In single mode it returns 1 if
316 there are no more available messages - any other result is a
317 fatal failure code! */
318 int pkgAcqMethod::Run(bool Single
)
322 // Block if the message queue is empty
323 if (Messages
.empty() == true)
326 if (WaitFd(STDIN_FILENO
) == false)
328 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
332 // Single mode exits if the message queue is empty
333 if (Single
== true && Messages
.empty() == true)
336 string Message
= Messages
.front();
337 Messages
.erase(Messages
.begin());
339 // Fetch the message number
341 int Number
= strtol(Message
.c_str(),&End
,10);
342 if (End
== Message
.c_str())
344 cerr
<< "Malformed message!" << endl
;
351 if (Configuration(Message
) == false)
357 FetchItem
*Tmp
= new FetchItem
;
359 Tmp
->Uri
= LookupTag(Message
,"URI");
360 Tmp
->DestFile
= LookupTag(Message
,"FileName");
361 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
362 Tmp
->LastModified
= 0;
363 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
366 // Append it to the list
367 FetchItem
**I
= &Queue
;
368 for (; *I
!= 0; I
= &(*I
)->Next
);
373 // Notify that this item is to be fetched.
374 if (Fetch(Tmp
) == false)
386 // AcqMethod::Log - Send a log message /*{{{*/
387 // ---------------------------------------------------------------------
389 void pkgAcqMethod::Log(const char *Format
,...)
391 string CurrentURI
= "<UNKNOWN>";
393 CurrentURI
= Queue
->Uri
;
396 va_start(args
,Format
);
398 // sprintf the description
400 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n"
401 "Message: ",CurrentURI
.c_str());
403 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
406 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
410 // AcqMethod::Status - Send a status message /*{{{*/
411 // ---------------------------------------------------------------------
413 void pkgAcqMethod::Status(const char *Format
,...)
415 string CurrentURI
= "<UNKNOWN>";
417 CurrentURI
= Queue
->Uri
;
420 va_start(args
,Format
);
422 // sprintf the description
424 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n"
425 "Message: ",CurrentURI
.c_str());
427 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
430 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
435 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
436 // ---------------------------------------------------------------------
438 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
439 IMSHit(false), Size(0), ResumePoint(0)
443 // AcqMethod::FetchResult::TakeHashes - Load hashes /*{{{*/
444 // ---------------------------------------------------------------------
445 /* This hides the number of hashes we are supporting from the caller.
446 It just deals with the hash class. */
447 void pkgAcqMethod::FetchResult::TakeHashes(Hashes
&Hash
)
449 MD5Sum
= Hash
.MD5
.Result();
450 SHA1Sum
= Hash
.SHA1
.Result();