]>
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.2.1 2003/12/24 23:09:17 mdz 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 /*{{{*/
20 #include <apt-pkg/acquire-method.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/configuration.h>
23 #include <apt-pkg/strutl.h>
24 #include <apt-pkg/fileutl.h>
25 #include <apt-pkg/hashes.h>
29 #include <sys/signal.h>
34 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
35 // ---------------------------------------------------------------------
36 /* This constructs the initialization text */
37 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
39 std::cout
<< "100 Capabilities\n"
40 << "Version: " << Ver
<< "\n";
42 if ((Flags
& SingleInstance
) == SingleInstance
)
43 std::cout
<< "Single-Instance: true\n";
45 if ((Flags
& Pipeline
) == Pipeline
)
46 std::cout
<< "Pipeline: true\n";
48 if ((Flags
& SendConfig
) == SendConfig
)
49 std::cout
<< "Send-Config: true\n";
51 if ((Flags
& LocalOnly
) == LocalOnly
)
52 std::cout
<<"Local-Only: true\n";
54 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
55 std::cout
<< "Needs-Cleanup: true\n";
57 if ((Flags
& Removable
) == Removable
)
58 std::cout
<< "Removable: true\n";
60 std::cout
<< "\n" << std::flush
;
62 SetNonBlock(STDIN_FILENO
,true);
68 // AcqMethod::Fail - A fetch has failed /*{{{*/
69 // ---------------------------------------------------------------------
71 void pkgAcqMethod::Fail(bool Transient
)
73 string Err
= "Undetermined Error";
74 if (_error
->empty() == false)
75 _error
->PopMessage(Err
);
80 // AcqMethod::Fail - A fetch has failed /*{{{*/
81 // ---------------------------------------------------------------------
83 void pkgAcqMethod::Fail(string Err
,bool Transient
)
85 // Strip out junk from the error messages
86 for (string::iterator I
= Err
.begin(); I
!= Err
.end(); ++I
)
96 std::cout
<< "400 URI Failure\nURI: " << Queue
->Uri
<< "\n"
97 << "Message: " << Err
<< " " << IP
<< "\n";
101 std::cout
<< "400 URI Failure\nURI: <UNKNOWN>\nMessage: " << Err
<< "\n";
103 if(FailReason
.empty() == false)
104 std::cout
<< "FailReason: " << FailReason
<< "\n";
105 if (UsedMirror
.empty() == false)
106 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
107 // Set the transient flag
108 if (Transient
== true)
109 std::cout
<< "Transient-Failure: true\n";
111 std::cout
<< "\n" << std::flush
;
114 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
115 // ---------------------------------------------------------------------
117 void pkgAcqMethod::URIStart(FetchResult
&Res
)
122 std::cout
<< "200 URI Start\n"
123 << "URI: " << Queue
->Uri
<< "\n";
125 std::cout
<< "Size: " << Res
.Size
<< "\n";
127 if (Res
.LastModified
!= 0)
128 std::cout
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n";
130 if (Res
.ResumePoint
!= 0)
131 std::cout
<< "Resume-Point: " << Res
.ResumePoint
<< "\n";
133 if (UsedMirror
.empty() == false)
134 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
136 std::cout
<< "\n" << std::flush
;
139 // AcqMethod::URIDone - A URI is finished /*{{{*/
140 // ---------------------------------------------------------------------
142 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
147 std::cout
<< "201 URI Done\n"
148 << "URI: " << Queue
->Uri
<< "\n";
150 if (Res
.Filename
.empty() == false)
151 std::cout
<< "Filename: " << Res
.Filename
<< "\n";
154 std::cout
<< "Size: " << Res
.Size
<< "\n";
156 if (Res
.LastModified
!= 0)
157 std::cout
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n";
159 if (Res
.MD5Sum
.empty() == false)
160 std::cout
<< "MD5-Hash: " << Res
.MD5Sum
<< "\n"
161 << "MD5Sum-Hash: " << Res
.MD5Sum
<< "\n";
162 if (Res
.SHA1Sum
.empty() == false)
163 std::cout
<< "SHA1-Hash: " << Res
.SHA1Sum
<< "\n";
164 if (Res
.SHA256Sum
.empty() == false)
165 std::cout
<< "SHA256-Hash: " << Res
.SHA256Sum
<< "\n";
166 if (Res
.SHA512Sum
.empty() == false)
167 std::cout
<< "SHA512-Hash: " << Res
.SHA512Sum
<< "\n";
168 if (UsedMirror
.empty() == false)
169 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
170 if (Res
.GPGVOutput
.empty() == false)
172 std::cout
<< "GPGVOutput:\n";
173 for (vector
<string
>::const_iterator I
= Res
.GPGVOutput
.begin();
174 I
!= Res
.GPGVOutput
.end(); ++I
)
175 std::cout
<< " " << *I
<< "\n";
178 if (Res
.ResumePoint
!= 0)
179 std::cout
<< "Resume-Point: " << Res
.ResumePoint
<< "\n";
181 if (Res
.IMSHit
== true)
182 std::cout
<< "IMS-Hit: true\n";
186 if (Alt
->Filename
.empty() == false)
187 std::cout
<< "Alt-Filename: " << Alt
->Filename
<< "\n";
190 std::cout
<< "Alt-Size: " << Alt
->Size
<< "\n";
192 if (Alt
->LastModified
!= 0)
193 std::cout
<< "Alt-Last-Modified: " << TimeRFC1123(Alt
->LastModified
) << "\n";
195 if (Alt
->MD5Sum
.empty() == false)
196 std::cout
<< "Alt-MD5-Hash: " << Alt
->MD5Sum
<< "\n";
197 if (Alt
->SHA1Sum
.empty() == false)
198 std::cout
<< "Alt-SHA1-Hash: " << Alt
->SHA1Sum
<< "\n";
199 if (Alt
->SHA256Sum
.empty() == false)
200 std::cout
<< "Alt-SHA256-Hash: " << Alt
->SHA256Sum
<< "\n";
201 if (Alt
->SHA512Sum
.empty() == false)
202 std::cout
<< "Alt-SHA512-Hash: " << Alt
->SHA512Sum
<< "\n";
204 if (Alt
->IMSHit
== true)
205 std::cout
<< "Alt-IMS-Hit: true\n";
208 std::cout
<< "\n" << std::flush
;
212 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
213 // ---------------------------------------------------------------------
214 /* This sends a 403 Media Failure message to the APT and waits for it
216 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
218 fprintf(stdout
, "403 Media Failure\nMedia: %s\nDrive: %s\n",
219 Required
.c_str(),Drive
.c_str());
220 std::cout
<< "\n" << std::flush
;
222 vector
<string
> MyMessages
;
224 /* Here we read messages until we find a 603, each non 603 message is
225 appended to the main message list for later processing */
228 if (WaitFd(STDIN_FILENO
) == false)
231 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
234 string Message
= MyMessages
.front();
235 MyMessages
.erase(MyMessages
.begin());
237 // Fetch the message number
239 int Number
= strtol(Message
.c_str(),&End
,10);
240 if (End
== Message
.c_str())
242 cerr
<< "Malformed message!" << endl
;
249 while (MyMessages
.empty() == false)
251 Messages
.push_back(MyMessages
.front());
252 MyMessages
.erase(MyMessages
.begin());
255 return !StringToBool(LookupTag(Message
,"Failed"),false);
258 Messages
.push_back(Message
);
262 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
263 // ---------------------------------------------------------------------
264 /* This parses each configuration entry and puts it into the _config
265 Configuration class. */
266 bool pkgAcqMethod::Configuration(string Message
)
268 ::Configuration
&Cnf
= *_config
;
270 const char *I
= Message
.c_str();
271 const char *MsgEnd
= I
+ Message
.length();
273 unsigned int Length
= strlen("Config-Item");
274 for (; I
+ Length
< MsgEnd
; I
++)
277 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
282 for (; I
< MsgEnd
&& *I
== ' '; I
++);
283 const char *Equals
= (const char*) memchr(I
, '=', MsgEnd
- I
);
286 const char *End
= (const char*) memchr(Equals
, '\n', MsgEnd
- Equals
);
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)
313 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
317 // Single mode exits if the message queue is empty
318 if (Single
== true && Messages
.empty() == true)
321 string Message
= Messages
.front();
322 Messages
.erase(Messages
.begin());
324 // Fetch the message number
326 int Number
= strtol(Message
.c_str(),&End
,10);
327 if (End
== Message
.c_str())
329 cerr
<< "Malformed message!" << endl
;
336 if (Configuration(Message
) == false)
342 FetchItem
*Tmp
= new FetchItem
;
344 Tmp
->Uri
= LookupTag(Message
,"URI");
345 Tmp
->DestFile
= LookupTag(Message
,"FileName");
346 if (RFC1123StrToTime(LookupTag(Message
,"Last-Modified").c_str(),Tmp
->LastModified
) == false)
347 Tmp
->LastModified
= 0;
348 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
349 Tmp
->FailIgnore
= StringToBool(LookupTag(Message
,"Fail-Ignore"),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)
372 // AcqMethod::PrintStatus - privately really send a log/status message /*{{{*/
373 // ---------------------------------------------------------------------
375 void pkgAcqMethod::PrintStatus(char const * const header
, const char* Format
,
378 string CurrentURI
= "<UNKNOWN>";
380 CurrentURI
= Queue
->Uri
;
381 if (UsedMirror
.empty() == true)
382 fprintf(stdout
, "%s\nURI: %s\nMessage: ",
383 header
, CurrentURI
.c_str());
385 fprintf(stdout
, "%s\nURI: %s\nUsedMirror: %s\nMessage: ",
386 header
, CurrentURI
.c_str(), UsedMirror
.c_str());
387 vfprintf(stdout
,Format
,args
);
388 std::cout
<< "\n\n" << std::flush
;
391 // AcqMethod::Log - Send a log message /*{{{*/
392 // ---------------------------------------------------------------------
394 void pkgAcqMethod::Log(const char *Format
,...)
397 va_start(args
,Format
);
398 PrintStatus("101 Log", Format
, args
);
402 // AcqMethod::Status - Send a status message /*{{{*/
403 // ---------------------------------------------------------------------
405 void pkgAcqMethod::Status(const char *Format
,...)
408 va_start(args
,Format
);
409 PrintStatus("102 Status", Format
, args
);
413 // AcqMethod::Redirect - Send a redirect message /*{{{*/
414 // ---------------------------------------------------------------------
415 /* This method sends the redirect message and dequeues the item as
416 * the worker will enqueue again later on to the right queue */
417 void pkgAcqMethod::Redirect(const string
&NewURI
)
419 std::cout
<< "103 Redirect\nURI: " << Queue
->Uri
<< "\n"
420 << "New-URI: " << NewURI
<< "\n"
421 << "\n" << std::flush
;
425 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
426 // ---------------------------------------------------------------------
428 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
429 IMSHit(false), Size(0), ResumePoint(0)
433 // AcqMethod::FetchResult::TakeHashes - Load hashes /*{{{*/
434 // ---------------------------------------------------------------------
435 /* This hides the number of hashes we are supporting from the caller.
436 It just deals with the hash class. */
437 void pkgAcqMethod::FetchResult::TakeHashes(Hashes
&Hash
)
439 MD5Sum
= Hash
.MD5
.Result();
440 SHA1Sum
= Hash
.SHA1
.Result();
441 SHA256Sum
= Hash
.SHA256
.Result();
442 SHA512Sum
= Hash
.SHA512
.Result();
445 void pkgAcqMethod::Dequeue() { /*{{{*/
446 FetchItem
const * const Tmp
= Queue
;
448 if (Tmp
== QueueBack
)