]>
git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: acquire-method.cc,v 1.23 1999/12/09 21:18:01 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>
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");
58 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
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 (char *I
= Err
.begin(); I
!= Err
.end(); I
++)
96 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: %s\n"
97 "Message: %s\n",Queue
->Uri
.c_str(),Err
.c_str());
100 FetchItem
*Tmp
= Queue
;
103 if (Tmp
== QueueBack
)
107 snprintf(S
,sizeof(S
)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
108 "Message: %s\n",Err
.c_str());
110 // Set the transient flag
111 if (Transient
== true)
112 strcat(S
,"Transient-Failure: true\n\n");
116 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
120 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
121 // ---------------------------------------------------------------------
123 void pkgAcqMethod::URIStart(FetchResult
&Res
)
131 End
+= snprintf(S
,sizeof(S
),"200 URI Start\nURI: %s\n",Queue
->Uri
.c_str());
133 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Size: %lu\n",Res
.Size
);
135 if (Res
.LastModified
!= 0)
136 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Last-Modified: %s\n",
137 TimeRFC1123(Res
.LastModified
).c_str());
139 if (Res
.ResumePoint
!= 0)
140 End
+= snprintf(End
,sizeof(S
)-4 - (End
- S
),"Resume-Point: %lu\n",
144 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
148 // AcqMethod::URIDone - A URI is finished /*{{{*/
149 // ---------------------------------------------------------------------
151 void pkgAcqMethod::URIDone(FetchResult
&Res
, FetchResult
*Alt
)
159 End
+= snprintf(S
,sizeof(S
),"201 URI Done\nURI: %s\n",Queue
->Uri
.c_str());
161 if (Res
.Filename
.empty() == false)
162 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Filename: %s\n",Res
.Filename
.c_str());
165 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Size: %lu\n",Res
.Size
);
167 if (Res
.LastModified
!= 0)
168 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Last-Modified: %s\n",
169 TimeRFC1123(Res
.LastModified
).c_str());
171 if (Res
.MD5Sum
.empty() == false)
172 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"MD5-Hash: %s\n",Res
.MD5Sum
.c_str());
174 if (Res
.ResumePoint
!= 0)
175 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Resume-Point: %lu\n",
178 if (Res
.IMSHit
== true)
179 strcat(End
,"IMS-Hit: true\n");
184 if (Alt
->Filename
.empty() == false)
185 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Filename: %s\n",Alt
->Filename
.c_str());
188 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Size: %lu\n",Alt
->Size
);
190 if (Alt
->LastModified
!= 0)
191 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-Last-Modified: %s\n",
192 TimeRFC1123(Alt
->LastModified
).c_str());
194 if (Alt
->MD5Sum
.empty() == false)
195 End
+= snprintf(End
,sizeof(S
)-50 - (End
- S
),"Alt-MD5-Hash: %s\n",
196 Alt
->MD5Sum
.c_str());
198 if (Alt
->IMSHit
== true)
199 strcat(End
,"Alt-IMS-Hit: true\n");
203 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
207 FetchItem
*Tmp
= Queue
;
210 if (Tmp
== QueueBack
)
214 // AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
215 // ---------------------------------------------------------------------
216 /* This sends a 403 Media Failure message to the APT and waits for it
218 bool pkgAcqMethod::MediaFail(string Required
,string Drive
)
221 snprintf(S
,sizeof(S
),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
222 Required
.c_str(),Drive
.c_str());
224 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
227 vector
<string
> MyMessages
;
229 /* Here we read messages until we find a 603, each non 603 message is
230 appended to the main message list for later processing */
233 if (WaitFd(STDIN_FILENO
) == false)
236 if (ReadMessages(STDIN_FILENO
,MyMessages
) == false)
239 string Message
= MyMessages
.front();
240 MyMessages
.erase(MyMessages
.begin());
242 // Fetch the message number
244 int Number
= strtol(Message
.c_str(),&End
,10);
245 if (End
== Message
.c_str())
247 cerr
<< "Malformed message!" << endl
;
254 while (MyMessages
.empty() == false)
256 Messages
.push_back(MyMessages
.front());
257 MyMessages
.erase(MyMessages
.begin());
260 return !StringToBool(LookupTag(Message
,"Fail"),false);
263 Messages
.push_back(Message
);
267 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
268 // ---------------------------------------------------------------------
269 /* This parses each configuration entry and puts it into the _config
270 Configuration class. */
271 bool pkgAcqMethod::Configuration(string Message
)
273 ::Configuration
&Cnf
= *_config
;
275 const char *I
= Message
.begin();
277 unsigned int Length
= strlen("Config-Item");
278 for (; I
+ Length
< Message
.end(); I
++)
281 if (I
[Length
] != ':' || stringcasecmp(I
,I
+Length
,"Config-Item") != 0)
286 for (; I
< Message
.end() && *I
== ' '; I
++);
287 const char *Equals
= I
;
288 for (; Equals
< Message
.end() && *Equals
!= '='; Equals
++);
289 const char *End
= Equals
;
290 for (; End
< Message
.end() && *End
!= '\n'; End
++);
294 Cnf
.Set(DeQuoteString(string(I
,Equals
-I
)),
295 DeQuoteString(string(Equals
+1,End
-Equals
-1)));
302 // AcqMethod::Run - Run the message engine /*{{{*/
303 // ---------------------------------------------------------------------
304 /* Fetch any messages and execute them. In single mode it returns 1 if
305 there are no more available messages - any other result is a
306 fatal failure code! */
307 int pkgAcqMethod::Run(bool Single
)
311 // Block if the message queue is empty
312 if (Messages
.empty() == true)
315 if (WaitFd(STDIN_FILENO
) == false)
317 if (ReadMessages(STDIN_FILENO
,Messages
) == false)
321 // Single mode exits if the message queue is empty
322 if (Single
== true && Messages
.empty() == true)
325 string Message
= Messages
.front();
326 Messages
.erase(Messages
.begin());
328 // Fetch the message number
330 int Number
= strtol(Message
.c_str(),&End
,10);
331 if (End
== Message
.c_str())
333 cerr
<< "Malformed message!" << endl
;
340 if (Configuration(Message
) == false)
346 FetchItem
*Tmp
= new FetchItem
;
348 Tmp
->Uri
= LookupTag(Message
,"URI");
349 Tmp
->DestFile
= LookupTag(Message
,"FileName");
350 if (StrToTime(LookupTag(Message
,"Last-Modified"),Tmp
->LastModified
) == false)
351 Tmp
->LastModified
= 0;
352 Tmp
->IndexFile
= StringToBool(LookupTag(Message
,"Index-File"),false);
355 // Append it to the list
356 FetchItem
**I
= &Queue
;
357 for (; *I
!= 0; I
= &(*I
)->Next
);
362 // Notify that this item is to be fetched.
363 if (Fetch(Tmp
) == false)
375 // AcqMethod::Log - Send a log message /*{{{*/
376 // ---------------------------------------------------------------------
378 void pkgAcqMethod::Log(const char *Format
,...)
380 string CurrentURI
= "<UNKNOWN>";
382 CurrentURI
= Queue
->Uri
;
385 va_start(args
,Format
);
387 // sprintf the description
389 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"101 Log\nURI: %s\n"
390 "Message: ",CurrentURI
.c_str());
392 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
395 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
399 // AcqMethod::Status - Send a status message /*{{{*/
400 // ---------------------------------------------------------------------
402 void pkgAcqMethod::Status(const char *Format
,...)
404 string CurrentURI
= "<UNKNOWN>";
406 CurrentURI
= Queue
->Uri
;
409 va_start(args
,Format
);
411 // sprintf the description
413 unsigned int Len
= snprintf(S
,sizeof(S
)-4,"102 Status\nURI: %s\n"
414 "Message: ",CurrentURI
.c_str());
416 vsnprintf(S
+Len
,sizeof(S
)-4-Len
,Format
,args
);
419 if (write(STDOUT_FILENO
,S
,strlen(S
)) != (signed)strlen(S
))
424 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
425 // ---------------------------------------------------------------------
427 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
428 IMSHit(false), Size(0), ResumePoint(0)