]>
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> 
  27 #include <sys/signal.h> 
  32 // AcqMethod::pkgAcqMethod - Constructor                                /*{{{*/ 
  33 // --------------------------------------------------------------------- 
  34 /* This constructs the initialization text */ 
  35 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
) 
  37    std::cout 
<< "100 Capabilities\n" 
  38              << "Version: " << Ver 
<< "\n"; 
  40    if ((Flags 
& SingleInstance
) == SingleInstance
) 
  41       std::cout 
<< "Single-Instance: true\n"; 
  43    if ((Flags 
& Pipeline
) == Pipeline
) 
  44       std::cout 
<< "Pipeline: true\n"; 
  46    if ((Flags 
& SendConfig
) == SendConfig
) 
  47       std::cout 
<< "Send-Config: true\n"; 
  49    if ((Flags 
& LocalOnly
) == LocalOnly
) 
  50       std::cout 
<<"Local-Only: true\n"; 
  52    if ((Flags 
& NeedsCleanup
) == NeedsCleanup
) 
  53       std::cout 
<< "Needs-Cleanup: true\n"; 
  55    if ((Flags 
& Removable
) == Removable
) 
  56       std::cout 
<< "Removable: true\n"; 
  58    std::cout 
<< "\n" << std::flush
; 
  60    SetNonBlock(STDIN_FILENO
,true); 
  66 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  67 // --------------------------------------------------------------------- 
  69 void pkgAcqMethod::Fail(bool Transient
) 
  71    string Err 
= "Undetermined Error"; 
  72    if (_error
->empty() == false) 
  73       _error
->PopMessage(Err
);    
  78 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  79 // --------------------------------------------------------------------- 
  81 void pkgAcqMethod::Fail(string Err
,bool Transient
) 
  83    // Strip out junk from the error messages 
  84    for (string::iterator I 
= Err
.begin(); I 
!= Err
.end(); I
++) 
  94       std::cout 
<< "400 URI Failure\nURI: " << Queue
->Uri 
<< "\n" 
  95                 << "Message: " << Err 
<< " " << IP 
<< "\n"; 
  97       FetchItem 
*Tmp 
= Queue
; 
 100       if (Tmp 
== QueueBack
) 
 104       std::cout 
<< "400 URI Failure\nURI: <UNKNOWN>\nMessage: " << Err 
<< "\n"; 
 106    if(FailReason
.empty() == false) 
 107       std::cout 
<< "FailReason: " << FailReason 
<< "\n"; 
 108    if (UsedMirror
.empty() == false) 
 109       std::cout 
<< "UsedMirror: " << UsedMirror 
<< "\n"; 
 110    // Set the transient flag 
 111    if (Transient 
== true) 
 112       std::cout 
<< "Transient-Failure: true\n"; 
 114    std::cout 
<< "\n" << std::flush
; 
 117 // AcqMethod::URIStart - Indicate a download is starting                /*{{{*/ 
 118 // --------------------------------------------------------------------- 
 120 void pkgAcqMethod::URIStart(FetchResult 
&Res
) 
 125    std::cout 
<< "200 URI Start\n" 
 126              << "URI: " << Queue
->Uri 
<< "\n"; 
 128       std::cout 
<< "Size: " << Res
.Size 
<< "\n"; 
 130    if (Res
.LastModified 
!= 0) 
 131       std::cout 
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n"; 
 133    if (Res
.ResumePoint 
!= 0) 
 134       std::cout 
<< "Resume-Point: " << Res
.ResumePoint 
<< "\n"; 
 136    if (UsedMirror
.empty() == false) 
 137       std::cout 
<< "UsedMirror: " << UsedMirror 
<< "\n"; 
 139    std::cout 
<< "\n" << std::flush
; 
 142 // AcqMethod::URIDone - A URI is finished                               /*{{{*/ 
 143 // --------------------------------------------------------------------- 
 145 void pkgAcqMethod::URIDone(FetchResult 
&Res
, FetchResult 
*Alt
) 
 150    std::cout 
<< "201 URI Done\n" 
 151              << "URI: " << Queue
->Uri 
<< "\n"; 
 153    if (Res
.Filename
.empty() == false) 
 154       std::cout 
<< "Filename: " << Res
.Filename 
<< "\n"; 
 157       std::cout 
<< "Size: " << Res
.Size 
<< "\n"; 
 159    if (Res
.LastModified 
!= 0) 
 160       std::cout 
<< "Last-Modified: " << TimeRFC1123(Res
.LastModified
) << "\n"; 
 162    if (Res
.MD5Sum
.empty() == false) 
 163       std::cout 
<< "MD5-Hash: " << Res
.MD5Sum 
<< "\n" 
 164                 << "MD5Sum-Hash: " << Res
.MD5Sum 
<< "\n"; 
 165    if (Res
.SHA1Sum
.empty() == false) 
 166       std::cout 
<< "SHA1-Hash: " << Res
.SHA1Sum 
<< "\n"; 
 167    if (Res
.SHA256Sum
.empty() == false) 
 168       std::cout 
<< "SHA256-Hash: " << Res
.SHA256Sum 
<< "\n"; 
 169    if (Res
.SHA512Sum
.empty() == false) 
 170       std::cout 
<< "SHA512-Hash: " << Res
.SHA512Sum 
<< "\n"; 
 171    if (UsedMirror
.empty() == false) 
 172       std::cout 
<< "UsedMirror: " << UsedMirror 
<< "\n"; 
 173    if (Res
.GPGVOutput
.empty() == false) 
 175       std::cout 
<< "GPGVOutput:\n"; 
 176       for (vector
<string
>::const_iterator I 
= Res
.GPGVOutput
.begin(); 
 177            I 
!= Res
.GPGVOutput
.end(); ++I
) 
 178          std::cout 
<< " " << *I 
<< "\n"; 
 181    if (Res
.ResumePoint 
!= 0) 
 182       std::cout 
<< "Resume-Point: " << Res
.ResumePoint 
<< "\n"; 
 184    if (Res
.IMSHit 
== true) 
 185       std::cout 
<< "IMS-Hit: true\n"; 
 189       if (Alt
->Filename
.empty() == false) 
 190          std::cout 
<< "Alt-Filename: " << Alt
->Filename 
<< "\n"; 
 193          std::cout 
<< "Alt-Size: " << Alt
->Size 
<< "\n"; 
 195       if (Alt
->LastModified 
!= 0) 
 196          std::cout 
<< "Alt-Last-Modified: " << TimeRFC1123(Alt
->LastModified
) << "\n"; 
 198       if (Alt
->MD5Sum
.empty() == false) 
 199          std::cout 
<< "Alt-MD5-Hash: " << Alt
->MD5Sum 
<< "\n"; 
 200       if (Alt
->SHA1Sum
.empty() == false) 
 201          std::cout 
<< "Alt-SHA1-Hash: " << Alt
->SHA1Sum 
<< "\n"; 
 202       if (Alt
->SHA256Sum
.empty() == false) 
 203          std::cout 
<< "Alt-SHA256-Hash: " << Alt
->SHA256Sum 
<< "\n"; 
 204       if (Alt
->SHA512Sum
.empty() == false) 
 205          std::cout 
<< "Alt-SHA512-Hash: " << Alt
->SHA512Sum 
<< "\n"; 
 207       if (Alt
->IMSHit 
== true) 
 208          std::cout 
<< "Alt-IMS-Hit: true\n"; 
 211    std::cout 
<< "\n" << std::flush
; 
 214    FetchItem 
*Tmp 
= Queue
; 
 217    if (Tmp 
== QueueBack
) 
 221 // AcqMethod::MediaFail - Syncronous request for new media              /*{{{*/ 
 222 // --------------------------------------------------------------------- 
 223 /* This sends a 403 Media Failure message to the APT and waits for it 
 225 bool pkgAcqMethod::MediaFail(string Required
,string Drive
) 
 227    fprintf(stdout
, "403 Media Failure\nMedia: %s\nDrive: %s\n", 
 228             Required
.c_str(),Drive
.c_str()); 
 229    std::cout 
<< "\n" << std::flush
; 
 231    vector
<string
> MyMessages
; 
 233    /* Here we read messages until we find a 603, each non 603 message is 
 234       appended to the main message list for later processing */ 
 237       if (WaitFd(STDIN_FILENO
) == false) 
 240       if (ReadMessages(STDIN_FILENO
,MyMessages
) == false) 
 243       string Message 
= MyMessages
.front(); 
 244       MyMessages
.erase(MyMessages
.begin()); 
 246       // Fetch the message number 
 248       int Number 
= strtol(Message
.c_str(),&End
,10); 
 249       if (End 
== Message
.c_str()) 
 251          cerr 
<< "Malformed message!" << endl
; 
 258          while (MyMessages
.empty() == false) 
 260             Messages
.push_back(MyMessages
.front()); 
 261             MyMessages
.erase(MyMessages
.begin()); 
 264          return !StringToBool(LookupTag(Message
,"Failed"),false); 
 267       Messages
.push_back(Message
); 
 271 // AcqMethod::Configuration - Handle the configuration message          /*{{{*/ 
 272 // --------------------------------------------------------------------- 
 273 /* This parses each configuration entry and puts it into the _config  
 274    Configuration class. */ 
 275 bool pkgAcqMethod::Configuration(string Message
) 
 277    ::Configuration 
&Cnf 
= *_config
; 
 279    const char *I 
= Message
.c_str(); 
 280    const char *MsgEnd 
= I 
+ Message
.length(); 
 282    unsigned int Length 
= strlen("Config-Item"); 
 283    for (; I 
+ Length 
< MsgEnd
; I
++) 
 286       if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0) 
 291       for (; I 
< MsgEnd 
&& *I 
== ' '; I
++); 
 292       const char *Equals 
= I
; 
 293       for (; Equals 
< MsgEnd 
&& *Equals 
!= '='; Equals
++); 
 294       const char *End 
= Equals
; 
 295       for (; End 
< MsgEnd 
&& *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 (RFC1123StrToTime(LookupTag(Message
,"Last-Modified").c_str(),Tmp
->LastModified
) == false) 
 356                Tmp
->LastModified 
= 0; 
 357             Tmp
->IndexFile 
= StringToBool(LookupTag(Message
,"Index-File"),false); 
 358             Tmp
->FailIgnore 
= StringToBool(LookupTag(Message
,"Fail-Ignore"),false); 
 361             // Append it to the list 
 362             FetchItem 
**I 
= &Queue
; 
 363             for (; *I 
!= 0; I 
= &(*I
)->Next
); 
 368             // Notify that this item is to be fetched. 
 369             if (Fetch(Tmp
) == false) 
 381 // AcqMethod::PrintStatus - privately really send a log/status message  /*{{{*/ 
 382 // --------------------------------------------------------------------- 
 384 void pkgAcqMethod::PrintStatus(char const * const header
, const char* Format
, 
 387    string CurrentURI 
= "<UNKNOWN>"; 
 389       CurrentURI 
= Queue
->Uri
; 
 390    if (UsedMirror
.empty() == true) 
 391       fprintf(stdout
, "%s\nURI: %s\nMessage: ", 
 392               header
, CurrentURI
.c_str()); 
 394       fprintf(stdout
, "%s\nURI: %s\nUsedMirror: %s\nMessage: ", 
 395               header
, CurrentURI
.c_str(), UsedMirror
.c_str()); 
 396    vfprintf(stdout
,Format
,args
); 
 397    std::cout 
<< "\n\n" << std::flush
; 
 400 // AcqMethod::Log - Send a log message                                  /*{{{*/ 
 401 // --------------------------------------------------------------------- 
 403 void pkgAcqMethod::Log(const char *Format
,...) 
 406    va_start(args
,Format
); 
 407    PrintStatus("101 Log", Format
, args
); 
 411 // AcqMethod::Status - Send a status message                            /*{{{*/ 
 412 // --------------------------------------------------------------------- 
 414 void pkgAcqMethod::Status(const char *Format
,...) 
 417    va_start(args
,Format
); 
 418    PrintStatus("102 Status", Format
, args
); 
 422 // AcqMethod::Redirect - Send a redirect message                       /*{{{*/ 
 423 // --------------------------------------------------------------------- 
 424 /* This method sends the redirect message and also manipulates the queue 
 425    to keep the pipeline synchronized. */ 
 426 void pkgAcqMethod::Redirect(const string 
&NewURI
) 
 428    std::cout 
<< "103 Redirect\nURI: "; 
 430       std::cout 
<< Queue
->Uri 
<< "\n"; 
 432       std::cout 
<< "<UNKNOWN>\n"; 
 433    std::cout 
<< "New-URI: " << NewURI 
<< "\n" 
 434              << "\n" << std::flush
; 
 436    // Change the URI for the request. 
 439    /* To keep the pipeline synchronized, move the current request to 
 440       the end of the queue, past the end of the current pipeline. */ 
 442    for (I 
= Queue
; I
->Next 
!= 0; I 
= I
->Next
) ; 
 450 // AcqMethod::FetchResult::FetchResult - Constructor                    /*{{{*/ 
 451 // --------------------------------------------------------------------- 
 453 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), 
 454                                    IMSHit(false), Size(0), ResumePoint(0) 
 458 // AcqMethod::FetchResult::TakeHashes - Load hashes                     /*{{{*/ 
 459 // --------------------------------------------------------------------- 
 460 /* This hides the number of hashes we are supporting from the caller.  
 461    It just deals with the hash class. */ 
 462 void pkgAcqMethod::FetchResult::TakeHashes(Hashes 
&Hash
) 
 464    MD5Sum 
= Hash
.MD5
.Result(); 
 465    SHA1Sum 
= Hash
.SHA1
.Result(); 
 466    SHA256Sum 
= Hash
.SHA256
.Result(); 
 467    SHA512Sum 
= Hash
.SHA512
.Result();