]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: acquire-method.cc,v 1.20 1999/08/04 02:39:13 jgg Exp $ 
   4 /* ###################################################################### 
   8    This is a skeleton class that implements most of the functionality 
   9    of a method and some usefull 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> 
  31 // AcqMethod::pkgAcqMethod - Constructor                                /*{{{*/ 
  32 // --------------------------------------------------------------------- 
  33 /* This constructs the initialization text */ 
  34 pkgAcqMethod::pkgAcqMethod(const char *Ver
,unsigned long Flags
) 
  38    strcat(End
,"100 Capabilities\n"); 
  39    sprintf(End
+strlen(End
),"Version: %s\n",Ver
); 
  41    if ((Flags 
& SingleInstance
) == SingleInstance
) 
  42       strcat(End
,"Single-Instance: true\n"); 
  44    if ((Flags 
& Pipeline
) == Pipeline
) 
  45       strcat(End
,"Pipeline: true\n"); 
  47    if ((Flags 
& SendConfig
) == SendConfig
) 
  48       strcat(End
,"Send-Config: true\n"); 
  50    if ((Flags 
& LocalOnly
) == LocalOnly
) 
  51       strcat(End
,"Local-Only: true\n"); 
  54    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
  57    SetNonBlock(STDIN_FILENO
,true); 
  63 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  64 // --------------------------------------------------------------------- 
  66 void pkgAcqMethod::Fail(bool Transient
) 
  68    string Err 
= "Undetermined Error"; 
  69    if (_error
->empty() == false) 
  70       _error
->PopMessage(Err
);    
  75 // AcqMethod::Fail - A fetch has failed                                 /*{{{*/ 
  76 // --------------------------------------------------------------------- 
  78 void pkgAcqMethod::Fail(string Err
,bool Transient
) 
  80    // Strip out junk from the error messages 
  81    for (char *I 
= Err
.begin(); I 
!= Err
.end(); I
++) 
  92       snprintf(S
,sizeof(S
),"400 URI Failure\nURI: %s\n" 
  93                "Message: %s\n",Queue
->Uri
.c_str(),Err
.c_str()); 
  96       FetchItem 
*Tmp 
= Queue
; 
 103       snprintf(S
,sizeof(S
),"400 URI Failure\nURI: <UNKNOWN>\n" 
 104                "Message: %s\n",Err
.c_str()); 
 106    // Set the transient flag  
 107    if (Transient 
== true) 
 108       strcat(S
,"Transient-Failure: true\n\n"); 
 112    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 116 // AcqMethod::URIStart - Indicate a download is starting                /*{{{*/ 
 117 // --------------------------------------------------------------------- 
 119 void pkgAcqMethod::URIStart(FetchResult 
&Res
) 
 127    End 
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str()); 
 129       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Size: %lu\n",Res
.Size
); 
 131    if (Res
.LastModified 
!= 0) 
 132       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Last-Modified: %s\n", 
 133                       TimeRFC1123(Res
.LastModified
).c_str()); 
 135    if (Res
.ResumePoint 
!= 0) 
 136       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Resume-Point: %lu\n", 
 140    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 144 // AcqMethod::URIDone - A URI is finished                               /*{{{*/ 
 145 // --------------------------------------------------------------------- 
 147 void pkgAcqMethod::URIDone(FetchResult 
&Res
, FetchResult 
*Alt
) 
 155    End 
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str()); 
 157    if (Res
.Filename
.empty() == false) 
 158       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Filename: %s\n",Res
.Filename
.c_str()); 
 161       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Size: %lu\n",Res
.Size
); 
 163    if (Res
.LastModified 
!= 0) 
 164       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Last-Modified: %s\n", 
 165                       TimeRFC1123(Res
.LastModified
).c_str()); 
 167    if (Res
.MD5Sum
.empty() == false) 
 168       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str()); 
 170    if (Res
.ResumePoint 
!= 0) 
 171       End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Resume-Point: %lu\n", 
 174    if (Res
.IMSHit 
== true) 
 175       strcat(End
,"IMS-Hit: true\n"); 
 180       if (Alt
->Filename
.empty() == false) 
 181          End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str()); 
 184          End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Alt-Size: %lu\n",Alt
->Size
); 
 186       if (Alt
->LastModified 
!= 0) 
 187          End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Alt-Last-Modified: %s\n", 
 188                          TimeRFC1123(Alt
->LastModified
).c_str()); 
 190       if (Alt
->MD5Sum
.empty() == false) 
 191          End 
+= snprintf(End
,sizeof(S
) - (End 
- S
),"Alt-MD5-Hash: %s\n", 
 192                          Alt
->MD5Sum
.c_str()); 
 194       if (Alt
->IMSHit 
== true) 
 195          strcat(End
,"Alt-IMS-Hit: true\n"); 
 199    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 203    FetchItem 
*Tmp 
= Queue
; 
 206    if (Tmp 
== QueueBack
) 
 210 // AcqMethod::MediaFail - Syncronous request for new media              /*{{{*/ 
 211 // --------------------------------------------------------------------- 
 212 /* This sends a 403 Media Failure message to the APT and waits for it 
 214 bool pkgAcqMethod::MediaFail(string Required
,string Drive
) 
 217    snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n", 
 218             Required
.c_str(),Drive
.c_str()); 
 220    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 223    vector
<string
> MyMessages
; 
 225    /* Here we read messages until we find a 603, each non 603 message is 
 226       appended to the main message list for later processing */ 
 229       if (WaitFd(STDIN_FILENO
) == false) 
 232       if (ReadMessages(STDIN_FILENO
,MyMessages
) == false) 
 235       string Message 
= MyMessages
.front(); 
 236       MyMessages
.erase(MyMessages
.begin()); 
 238       // Fetch the message number 
 240       int Number 
= strtol(Message
.c_str(),&End
,10); 
 241       if (End 
== Message
.c_str()) 
 243          cerr 
<< "Malformed message!" << endl
; 
 250          while (MyMessages
.empty() == false) 
 252             Messages
.push_back(MyMessages
.front()); 
 253             MyMessages
.erase(MyMessages
.begin()); 
 256          return !StringToBool(LookupTag(Message
,"Fail"),false); 
 259       Messages
.push_back(Message
); 
 263 // AcqMethod::Configuration - Handle the configuration message          /*{{{*/ 
 264 // --------------------------------------------------------------------- 
 265 /* This parses each configuration entry and puts it into the _config  
 266    Configuration class. */ 
 267 bool pkgAcqMethod::Configuration(string Message
) 
 269    ::Configuration 
&Cnf 
= *_config
; 
 271    const char *I 
= Message
.begin(); 
 273    unsigned int Length 
= strlen("Config-Item"); 
 274    for (; I 
+ Length 
< Message
.end(); I
++) 
 277       if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0) 
 282       for (; I 
< Message
.end() && *I 
== ' '; I
++); 
 283       const char *Equals 
= I
; 
 284       for (; Equals 
< Message
.end() && *Equals 
!= '='; Equals
++); 
 285       const char *End 
= Equals
; 
 286       for (; End 
< Message
.end() && *End 
!= '\n'; End
++); 
 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) 
 314          if (ReadMessages(STDIN_FILENO
,Messages
) == false) 
 318       // Single mode exits if the message queue is empty 
 319       if (Single 
== true && Messages
.empty() == true) 
 322       string Message 
= Messages
.front(); 
 323       Messages
.erase(Messages
.begin()); 
 325       // Fetch the message number 
 327       int Number 
= strtol(Message
.c_str(),&End
,10); 
 328       if (End 
== Message
.c_str()) 
 330          cerr 
<< "Malformed message!" << endl
; 
 337          if (Configuration(Message
) == false) 
 343             FetchItem 
*Tmp 
= new FetchItem
; 
 345             Tmp
->Uri 
= LookupTag(Message
,"URI"); 
 346             Tmp
->DestFile 
= LookupTag(Message
,"FileName"); 
 347             if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false) 
 348                Tmp
->LastModified 
= 0; 
 349             Tmp
->IndexFile 
= StringToBool(LookupTag(Message
,"Index-File"),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) 
 371 // AcqMethod::Log - Send a log message                                  /*{{{*/ 
 372 // --------------------------------------------------------------------- 
 374 void pkgAcqMethod::Log(const char *Format
,...) 
 376    string CurrentURI 
= "<UNKNOWN>"; 
 378       CurrentURI 
= Queue
->Uri
; 
 381    va_start(args
,Format
); 
 383    // sprintf the description 
 385    unsigned int Len 
= snprintf(S
,sizeof(S
),"101 Log\nURI: %s\n" 
 386                                "Message: ",CurrentURI
.c_str()); 
 388    vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
); 
 391    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 395 // AcqMethod::Status - Send a status message                            /*{{{*/ 
 396 // --------------------------------------------------------------------- 
 398 void pkgAcqMethod::Status(const char *Format
,...) 
 400    string CurrentURI 
= "<UNKNOWN>"; 
 402       CurrentURI 
= Queue
->Uri
; 
 405    va_start(args
,Format
); 
 407    // sprintf the description 
 409    unsigned int Len 
= snprintf(S
,sizeof(S
),"102 Status\nURI: %s\n" 
 410                                "Message: ",CurrentURI
.c_str()); 
 412    vsnprintf(S
+Len
,sizeof(S
)-Len
,Format
,args
); 
 415    if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
)) 
 420 // AcqMethod::FetchResult::FetchResult - Constructor                    /*{{{*/ 
 421 // --------------------------------------------------------------------- 
 423 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), 
 424                                    IMSHit(false), Size(0), ResumePoint(0)