]>
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 /*{{{*/
18 #include <apt-pkg/acquire-method.h>
19 #include <apt-pkg/error.h>
20 #include <apt-pkg/configuration.h>
21 #include <apt-pkg/strutl.h>
22 #include <apt-pkg/fileutl.h>
23 #include <apt-pkg/hashes.h>
28 #include <sys/signal.h>
33 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
34 // ---------------------------------------------------------------------
35 /* This constructs the initialization text */
36 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
)
38 std::cout
<< "100 Capabilities\n"
39 << "Version: " << Ver
<< "\n";
41 if ((Flags
& SingleInstance
) == SingleInstance
)
42 std::cout
<< "Single-Instance: true\n";
44 if ((Flags
& Pipeline
) == Pipeline
)
45 std::cout
<< "Pipeline: true\n";
47 if ((Flags
& SendConfig
) == SendConfig
)
48 std::cout
<< "Send-Config: true\n";
50 if ((Flags
& LocalOnly
) == LocalOnly
)
51 std::cout
<<"Local-Only: true\n";
53 if ((Flags
& NeedsCleanup
) == NeedsCleanup
)
54 std::cout
<< "Needs-Cleanup: true\n";
56 if ((Flags
& Removable
) == Removable
)
57 std::cout
<< "Removable: true\n";
59 std::cout
<< "\n" << std::flush
;
61 SetNonBlock(STDIN_FILENO
,true);
67 // AcqMethod::Fail - A fetch has failed /*{{{*/
68 // ---------------------------------------------------------------------
70 void pkgAcqMethod::Fail(bool Transient
)
72 string Err
= "Undetermined Error";
73 if (_error
->empty() == false)
74 _error
->PopMessage(Err
);
79 // AcqMethod::Fail - A fetch has failed /*{{{*/
80 // ---------------------------------------------------------------------
82 void pkgAcqMethod::Fail(string Err
,bool Transient
)
84 // Strip out junk from the error messages
85 for (string::iterator I
= Err
.begin(); I
!= Err
.end(); I
++)
95 std::cout
<< "400 URI Failure\nURI: " << Queue
->Uri
<< "\n"
96 << "Message: " << Err
<< " " << IP
<< "\n";
98 FetchItem
*Tmp
= Queue
;
101 if (Tmp
== QueueBack
)
105 std::cout
<< "400 URI Failure\nURI: <UNKNOWN>\nMessage: " << Err
<< "\n";
107 if(FailReason
.empty() == false)
108 std::cout
<< "FailReason: " << FailReason
<< "\n";
109 if (UsedMirror
.empty() == false)
110 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
111 // Set the transient flag
112 if (Transient
== true)
113 std::cout
<< "Transient-Failure: true\n";
115 std::cout
<< "\n" << std::flush
;
118 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
119 // ---------------------------------------------------------------------
121 void pkgAcqMethod::URIStart(FetchResult
&Res
)
126 std::cout
<< "200 URI Start\n"
127 << "URI: " << Queue
->Uri
<< "\n";
129 std::cout
<< "Size: " << Res
.Size
<< "\n";
131 if (Res
.LastModified
!= 0)
132 std::cout
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n";
134 if (Res
.ResumePoint
!= 0)
135 std::cout
<< "Resume-Point: " << Res
.ResumePoint
<< "\n";
137 if (UsedMirror
.empty() == false)
138 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
140 std::cout
<< "\n" << std::flush
;
143 // AcqMethod::URIDone - A URI is finished /*{{{*/
144 // ---------------------------------------------------------------------
146 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
151 std::cout
<< "201 URI Done\n"
152 << "URI: " << Queue
->Uri
<< "\n";
154 if (Res
.Filename
.empty() == false)
155 std::cout
<< "Filename: " << Res
.Filename
<< "\n";
158 std::cout
<< "Size: " << Res
.Size
<< "\n";
160 if (Res
.LastModified
!= 0)
161 std::cout
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n";
163 if (Res
.MD5Sum
.empty() == false)
164 std::cout
<< "MD5-Hash: " << Res
.MD5Sum
<< "\n"
165 << "MD5Sum-Hash: " << Res
.MD5Sum
<< "\n";
166 if (Res
.SHA1Sum
.empty() == false)
167 std::cout
<< "SHA1-Hash: " << Res
.SHA1Sum
<< "\n";
168 if (Res
.SHA256Sum
.empty() == false)
169 std::cout
<< "SHA256-Hash: " << Res
.SHA256Sum
<< "\n";
170 if (UsedMirror
.empty() == false)
171 std::cout
<< "UsedMirror: " << UsedMirror
<< "\n";
172 if (Res
.GPGVOutput
.empty() == false)
174 std::cout
<< "GPGVOutput:\n";
175 for (vector
<string
>::const_iterator I
= Res
.GPGVOutput
.begin();
176 I
!= Res
.GPGVOutput
.end(); ++I
)
177 std::cout
<< " " << *I
<< "\n";
180 if (Res
.ResumePoint
!= 0)
181 std::cout
<< "Resume-Point: " << Res
.ResumePoint
<< "\n";
183 if (Res
.IMSHit
== true)
184 std::cout
<< "IMS-Hit: true\n";
188 if (Alt
->Filename
.empty() == false)
189 std::cout
<< "Alt-Filename: " << Alt
->Filename
<< "\n";
192 std::cout
<< "Alt-Size: " << Alt
->Size
<< "\n";
194 if (Alt
->LastModified
!= 0)
195 std::cout
<< "Alt-Last-Modified: " << TimeRFC1123(Alt
->LastModified
) << "\n";
197 if (Alt
->MD5Sum
.empty() == false)
198 std::cout
<< "Alt-MD5-Hash: " << Alt
->MD5Sum
<< "\n";
199 if (Alt
->SHA1Sum
.empty() == false)
200 std::cout
<< "Alt-SHA1-Hash: " << Alt
->SHA1Sum
<< "\n";
201 if (Alt
->SHA256Sum
.empty() == false)
202 std::cout
<< "Alt-SHA256-Hash: " << Alt
->SHA256Sum
<< "\n";
204 if (Alt
->IMSHit
== true)
205 std::cout
<< "Alt-IMS-Hit: true\n";
208 std::cout
<< "\n" << std::flush
;
211 FetchItem
*Tmp
= Queue
;
214 if (Tmp
== QueueBack
)
218 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
219 // ---------------------------------------------------------------------
220 /* This sends a 403 Media Failure message to the APT and waits for it
222 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
224 fprintf(stdout
, "403 Media Failure\nMedia: %s\nDrive: %s\n",
225 Required
.c_str(),Drive
.c_str());
226 std::cout
<< "\n" << std::flush
;
228 vector
<string
> MyMessages
;
230 /* Here we read messages until we find a 603, each non 603 message is
231 appended to the main message list for later processing */
234 if (WaitFd(STDIN_FILENO
) == false)
237 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
240 string Message
= MyMessages
.front();
241 MyMessages
.erase(MyMessages
.begin());
243 // Fetch the message number
245 int Number
= strtol(Message
.c_str(),&End
,10);
246 if (End
== Message
.c_str())
248 cerr
<< "Malformed message!" << endl
;
255 while (MyMessages
.empty() == false)
257 Messages
.push_back(MyMessages
.front());
258 MyMessages
.erase(MyMessages
.begin());
261 return !StringToBool(LookupTag(Message
,"Failed"),false);
264 Messages
.push_back(Message
);
268 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
269 // ---------------------------------------------------------------------
270 /* This parses each configuration entry and puts it into the _config
271 Configuration class. */
272 bool pkgAcqMethod::Configuration(string Message
)
274 ::Configuration
&Cnf
= *_config
;
276 const char *I
= Message
.c_str();
277 const char *MsgEnd
= I
+ Message
.length();
279 unsigned int Length
= strlen("Config-Item");
280 for (; I
+ Length
< MsgEnd
; I
++)
283 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
288 for (; I
< MsgEnd
&& *I
== ' '; I
++);
289 const char *Equals
= I
;
290 for (; Equals
< MsgEnd
&& *Equals
!= '='; Equals
++);
291 const char *End
= Equals
;
292 for (; End
< MsgEnd
&& *End
!= '\n'; End
++);
296 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
297 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
304 // AcqMethod::Run - Run the message engine /*{{{*/
305 // ---------------------------------------------------------------------
306 /* Fetch any messages and execute them. In single mode it returns 1 if
307 there are no more available messages - any other result is a
308 fatal failure code! */
309 int pkgAcqMethod::Run(bool Single
)
313 // Block if the message queue is empty
314 if (Messages
.empty() == true)
317 if (WaitFd(STDIN_FILENO
) == false)
319 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
323 // Single mode exits if the message queue is empty
324 if (Single
== true && Messages
.empty() == true)
327 string Message
= Messages
.front();
328 Messages
.erase(Messages
.begin());
330 // Fetch the message number
332 int Number
= strtol(Message
.c_str(),&End
,10);
333 if (End
== Message
.c_str())
335 cerr
<< "Malformed message!" << endl
;
342 if (Configuration(Message
) == false)
348 FetchItem
*Tmp
= new FetchItem
;
350 Tmp
->Uri
= LookupTag(Message
,"URI");
351 Tmp
->DestFile
= LookupTag(Message
,"FileName");
352 if (RFC1123StrToTime(LookupTag(Message
,"Last-Modified").c_str(),Tmp
->LastModified
) == false)
353 Tmp
->LastModified
= 0;
354 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
355 Tmp
->FailIgnore
= StringToBool(LookupTag(Message
,"Fail-Ignore"),false);
358 // Append it to the list
359 FetchItem
**I
= &Queue
;
360 for (; *I
!= 0; I
= &(*I
)->Next
);
365 // Notify that this item is to be fetched.
366 if (Fetch(Tmp
) == false)
378 // AcqMethod::Log - Send a log message /*{{{*/
379 // ---------------------------------------------------------------------
381 void pkgAcqMethod::Log(const char *Format
,...)
383 string CurrentURI
= "<UNKNOWN>";
385 CurrentURI
= Queue
->Uri
;
386 fprintf(stdout
, "101 Log\nURI: %s\nUsedMirror: %s\nMessage: ",
387 UsedMirror
.c_str(), CurrentURI
.c_str());
390 va_start(args
,Format
);
391 vfprintf(stdout
,Format
,args
);
394 std::cout
<< "\n\n" << std::flush
;
397 // AcqMethod::Status - Send a status message /*{{{*/
398 // ---------------------------------------------------------------------
400 void pkgAcqMethod::Status(const char *Format
,...)
402 string CurrentURI
= "<UNKNOWN>";
404 CurrentURI
= Queue
->Uri
;
405 fprintf(stdout
, "102 Status\nURI: %s\nUsedMirror: %s\nMessage: ",
406 UsedMirror
.c_str(), CurrentURI
.c_str());
409 va_start(args
,Format
);
410 vfprintf(stdout
,Format
,args
);
413 std::cout
<< "\n\n" << std::flush
;
416 // AcqMethod::Redirect - Send a redirect message /*{{{*/
417 // ---------------------------------------------------------------------
418 /* This method sends the redirect message and also manipulates the queue
419 to keep the pipeline synchronized. */
420 void pkgAcqMethod::Redirect(const string
&NewURI
)
422 std::cout
<< "103 Redirect\nURI: ";
424 std::cout
<< Queue
->Uri
<< "\n";
426 std::cout
<< "<UNKNOWN>\n";
427 std::cout
<< "New-URI: " << NewURI
<< "\n"
428 << "\n" << std::flush
;
430 // Change the URI for the request.
433 /* To keep the pipeline synchronized, move the current request to
434 the end of the queue, past the end of the current pipeline. */
436 for (I
= Queue
; I
->Next
!= 0; I
= I
->Next
) ;
444 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
445 // ---------------------------------------------------------------------
447 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
448 IMSHit(false), Size(0), ResumePoint(0)
452 // AcqMethod::FetchResult::TakeHashes - Load hashes /*{{{*/
453 // ---------------------------------------------------------------------
454 /* This hides the number of hashes we are supporting from the caller.
455 It just deals with the hash class. */
456 void pkgAcqMethod::FetchResult::TakeHashes(Hashes
&Hash
)
458 MD5Sum
= Hash
.MD5
.Result();
459 SHA1Sum
= Hash
.SHA1
.Result();
460 SHA256Sum
= Hash
.SHA256
.Result();