]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: acquire-method.cc,v 1.25 2001/02/20 07:03:17 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> 
  32 // AcqMethod::pkgAcqMethod - Constructor                                /*{{{*/ 
  33 // --------------------------------------------------------------------- 
  34 /* This constructs the initialization text */ 
  35 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
) 
  39    strcat(End
,"100 Capabilities\n"); 
  40    sprintf(End
+strlen(End
),"Version: %s\n",Ver
); 
  42    if ((Flags 
& SingleInstance
) == SingleInstance
) 
  43       strcat(End
,"Single-Instance: true\n"); 
  45    if ((Flags 
& Pipeline
) == Pipeline
) 
  46       strcat(End
,"Pipeline: true\n"); 
  48    if ((Flags 
& SendConfig
) == SendConfig
) 
  49       strcat(End
,"Send-Config: true\n"); 
  51    if ((Flags 
& LocalOnly
) == LocalOnly
) 
  52       strcat(End
,"Local-Only: true\n"); 
  54    if ((Flags 
& NeedsCleanup
) == NeedsCleanup
) 
  55       strcat(End
,"Needs-Cleanup: true\n"); 
  57    if ((Flags 
& Removable
) == Removable
) 
  58       strcat(End
,"Removable: true\n"); 
  61    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
  64    SetNonBlock(STDIN_FILENO
,true); 
  70 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  71 // --------------------------------------------------------------------- 
  73 void pkgAcqMethod::Fail(bool Transient
) 
  75    string Err 
= "Undetermined Error"; 
  76    if (_error
->empty() == false) 
  77       _error
->PopMessage(Err
);    
  82 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  83 // --------------------------------------------------------------------- 
  85 void pkgAcqMethod::Fail(string Err
,bool Transient
) 
  87    // Strip out junk from the error messages 
  88    for (char *I 
= Err
.begin(); I 
!= Err
.end(); I
++) 
  99       snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: %s\n" 
 100                "Message: %s %s\n",Queue
->Uri
.c_str(),Err
.c_str(), 
 104       FetchItem 
*Tmp 
= Queue
; 
 107       if (Tmp 
== QueueBack
) 
 111       snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n" 
 112                "Message: %s %s\n",Err
.c_str(), 
 115    // Set the transient flag  
 116    if (Transient 
== true) 
 117       strcat(S
,"Transient-Failure: true\n\n"); 
 121    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 125 // AcqMethod::URIStart - Indicate a download is starting                /*{{{*/ 
 126 // --------------------------------------------------------------------- 
 128 void pkgAcqMethod::URIStart(FetchResult 
&Res
) 
 136    End 
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str()); 
 138       End 
+= snprintf(End
,sizeof(S
)-4 - (End 
- S
),"Size: %lu\n",Res
.Size
); 
 140    if (Res
.LastModified 
!= 0) 
 141       End 
+= snprintf(End
,sizeof(S
)-4 - (End 
- S
),"Last-Modified: %s\n", 
 142                       TimeRFC1123(Res
.LastModified
).c_str()); 
 144    if (Res
.ResumePoint 
!= 0) 
 145       End 
+= snprintf(End
,sizeof(S
)-4 - (End 
- S
),"Resume-Point: %lu\n", 
 149    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 153 // AcqMethod::URIDone - A URI is finished                               /*{{{*/ 
 154 // --------------------------------------------------------------------- 
 156 void pkgAcqMethod::URIDone(FetchResult 
&Res
, FetchResult 
*Alt
) 
 164    End 
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str()); 
 166    if (Res
.Filename
.empty() == false) 
 167       End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Filename: %s\n",Res
.Filename
.c_str()); 
 170       End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Size: %lu\n",Res
.Size
); 
 172    if (Res
.LastModified 
!= 0) 
 173       End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Last-Modified: %s\n", 
 174                       TimeRFC1123(Res
.LastModified
).c_str()); 
 176    if (Res
.MD5Sum
.empty() == false) 
 177       End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str()); 
 179    if (Res
.ResumePoint 
!= 0) 
 180       End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Resume-Point: %lu\n", 
 183    if (Res
.IMSHit 
== true) 
 184       strcat(End
,"IMS-Hit: true\n"); 
 189       if (Alt
->Filename
.empty() == false) 
 190          End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str()); 
 193          End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Alt-Size: %lu\n",Alt
->Size
); 
 195       if (Alt
->LastModified 
!= 0) 
 196          End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Alt-Last-Modified: %s\n", 
 197                          TimeRFC1123(Alt
->LastModified
).c_str()); 
 199       if (Alt
->MD5Sum
.empty() == false) 
 200          End 
+= snprintf(End
,sizeof(S
)-50 - (End 
- S
),"Alt-MD5-Hash: %s\n", 
 201                          Alt
->MD5Sum
.c_str()); 
 203       if (Alt
->IMSHit 
== true) 
 204          strcat(End
,"Alt-IMS-Hit: true\n"); 
 208    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 212    FetchItem 
*Tmp 
= Queue
; 
 215    if (Tmp 
== QueueBack
) 
 219 // AcqMethod::MediaFail - Syncronous request for new media              /*{{{*/ 
 220 // --------------------------------------------------------------------- 
 221 /* This sends a 403 Media Failure message to the APT and waits for it 
 223 bool pkgAcqMethod::MediaFail(string Required
,string Drive
) 
 226    snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n", 
 227             Required
.c_str(),Drive
.c_str()); 
 229    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 232    vector
<string
> MyMessages
; 
 234    /* Here we read messages until we find a 603, each non 603 message is 
 235       appended to the main message list for later processing */ 
 238       if (WaitFd(STDIN_FILENO
) == false) 
 241       if (ReadMessages(STDIN_FILENO
,MyMessages
) == false) 
 244       string Message 
= MyMessages
.front(); 
 245       MyMessages
.erase(MyMessages
.begin()); 
 247       // Fetch the message number 
 249       int Number 
= strtol(Message
.c_str(),&End
,10); 
 250       if (End 
== Message
.c_str()) 
 252          cerr 
<< "Malformed message!" << endl
; 
 259          while (MyMessages
.empty() == false) 
 261             Messages
.push_back(MyMessages
.front()); 
 262             MyMessages
.erase(MyMessages
.begin()); 
 265          return !StringToBool(LookupTag(Message
,"Fail"),false); 
 268       Messages
.push_back(Message
); 
 272 // AcqMethod::Configuration - Handle the configuration message          /*{{{*/ 
 273 // --------------------------------------------------------------------- 
 274 /* This parses each configuration entry and puts it into the _config  
 275    Configuration class. */ 
 276 bool pkgAcqMethod::Configuration(string Message
) 
 278    ::Configuration 
&Cnf 
= *_config
; 
 280    const char *I 
= Message
.begin(); 
 282    unsigned int Length 
= strlen("Config-Item"); 
 283    for (; I 
+ Length 
< Message
.end(); I
++) 
 286       if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0) 
 291       for (; I 
< Message
.end() && *I 
== ' '; I
++); 
 292       const char *Equals 
= I
; 
 293       for (; Equals 
< Message
.end() && *Equals 
!= '='; Equals
++); 
 294       const char *End 
= Equals
; 
 295       for (; End 
< Message
.end() && *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 (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false) 
 356                Tmp
->LastModified 
= 0; 
 357             Tmp
->IndexFile 
= StringToBool(LookupTag(Message
,"Index-File"),false); 
 360             // Append it to the list 
 361             FetchItem 
**I 
= &Queue
; 
 362             for (; *I 
!= 0; I 
= &(*I
)->Next
); 
 367             // Notify that this item is to be fetched. 
 368             if (Fetch(Tmp
) == false) 
 380 // AcqMethod::Log - Send a log message                                  /*{{{*/ 
 381 // --------------------------------------------------------------------- 
 383 void pkgAcqMethod::Log(const char *Format
,...) 
 385    string CurrentURI 
= "<UNKNOWN>"; 
 387       CurrentURI 
= Queue
->Uri
; 
 390    va_start(args
,Format
); 
 392    // sprintf the description 
 394    unsigned int Len 
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n" 
 395                                "Message: ",CurrentURI
.c_str()); 
 397    vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
); 
 400    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 404 // AcqMethod::Status - Send a status message                            /*{{{*/ 
 405 // --------------------------------------------------------------------- 
 407 void pkgAcqMethod::Status(const char *Format
,...) 
 409    string CurrentURI 
= "<UNKNOWN>"; 
 411       CurrentURI 
= Queue
->Uri
; 
 414    va_start(args
,Format
); 
 416    // sprintf the description 
 418    unsigned int Len 
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n" 
 419                                "Message: ",CurrentURI
.c_str()); 
 421    vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
); 
 424    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 429 // AcqMethod::FetchResult::FetchResult - Constructor                    /*{{{*/ 
 430 // --------------------------------------------------------------------- 
 432 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), 
 433                                    IMSHit(false), Size(0), ResumePoint(0)