]> git.saurik.com Git - apt.git/blob - apt-pkg/acquire-method.cc
706222c4058896615af9d1ab1e9f3a61cabcf468
[apt.git] / apt-pkg / acquire-method.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: acquire-method.cc,v 1.7 1998/11/11 07:30:54 jgg Exp $
4 /* ######################################################################
5
6 Acquire Method
7
8 ##################################################################### */
9 /*}}}*/
10 // Include Files /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/acquire-method.h"
13 #endif
14 #include <apt-pkg/acquire-method.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/configuration.h>
17 #include <strutl.h>
18 #include <apt-pkg/fileutl.h>
19
20 #include <stdio.h>
21 /*}}}*/
22
23 // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
24 // ---------------------------------------------------------------------
25 /* This constructs the initialization text */
26 pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
27 {
28 char S[300] = "";
29 char *End = S;
30 strcat(End,"100 Capabilities\n");
31 sprintf(End+strlen(End),"Version: %s\n",Ver);
32
33 if ((Flags & SingleInstance) == SingleInstance)
34 strcat(End,"Single-Instance: true\n");
35
36 if ((Flags & PreScan) == PreScan)
37 strcat(End,"Pre-Scan: true\n");
38
39 if ((Flags & Pipeline) == Pipeline)
40 strcat(End,"Pipeline: true\n");
41
42 if ((Flags & SendConfig) == SendConfig)
43 strcat(End,"Send-Config: true\n");
44 strcat(End,"\n");
45
46 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
47 exit(100);
48
49 SetNonBlock(STDIN_FILENO,true);
50
51 Queue = 0;
52 }
53 /*}}}*/
54 // AcqMethod::Fail - A fetch has failed /*{{{*/
55 // ---------------------------------------------------------------------
56 /* */
57 void pkgAcqMethod::Fail()
58 {
59 string Err = "Undetermined Error";
60 if (_error->empty() == false)
61 _error->PopMessage(Err);
62 _error->Discard();
63 Fail(Err);
64 }
65 /*}}}*/
66 // AcqMethod::Fail - A fetch has failed /*{{{*/
67 // ---------------------------------------------------------------------
68 /* */
69 void pkgAcqMethod::Fail(string Err)
70 {
71 char S[1024];
72 if (Queue != 0)
73 {
74 snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
75 "Message: %s\n\n",Queue->Uri.c_str(),Err.c_str());
76
77 // Dequeue
78 FetchItem *Tmp = Queue;
79 Queue = Queue->Next;
80 delete Tmp;
81 }
82 else
83 snprintf(S,sizeof(S),"400 URI Failure\nURI: <UNKNOWN>\n"
84 "Message: %s\n\n",Err.c_str());
85
86 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
87 exit(100);
88 }
89 /*}}}*/
90 // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
91 // ---------------------------------------------------------------------
92 /* */
93 void pkgAcqMethod::URIStart(FetchResult &Res)
94 {
95 if (Queue == 0)
96 abort();
97
98 char S[1024] = "";
99 char *End = S;
100
101 End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
102 if (Res.Size != 0)
103 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
104
105 if (Res.LastModified != 0)
106 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
107 TimeRFC1123(Res.LastModified).c_str());
108
109 if (Res.ResumePoint != 0)
110 End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
111 Res.ResumePoint);
112
113 strcat(End,"\n");
114 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
115 exit(100);
116 }
117 /*}}}*/
118 // AcqMethod::URIDone - A URI is finished /*{{{*/
119 // ---------------------------------------------------------------------
120 /* */
121 void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
122 {
123 if (Queue == 0)
124 abort();
125
126 char S[1024] = "";
127 char *End = S;
128
129 End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",Queue->Uri.c_str());
130
131 if (Res.Filename.empty() == false)
132 End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
133
134 if (Res.Size != 0)
135 End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
136
137 if (Res.LastModified != 0)
138 End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
139 TimeRFC1123(Res.LastModified).c_str());
140
141 if (Res.MD5Sum.empty() == false)
142 End += snprintf(End,sizeof(S) - (End - S),"MD5Sum: %s\n",Res.MD5Sum.c_str());
143
144 if (Res.ResumePoint != 0)
145 End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
146 Res.ResumePoint);
147
148 if (Res.IMSHit == true)
149 strcat(End,"IMS-Hit: true\n");
150 End = S + strlen(S);
151
152 if (Alt != 0)
153 {
154 if (Alt->Filename.empty() == false)
155 End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
156
157 if (Alt->Size != 0)
158 End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
159
160 if (Alt->LastModified != 0)
161 End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
162 TimeRFC1123(Alt->LastModified).c_str());
163
164 if (Alt->MD5Sum.empty() == false)
165 End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5Sum: %s\n",
166 Alt->MD5Sum.c_str());
167
168 if (Alt->IMSHit == true)
169 strcat(End,"Alt-IMS-Hit: true\n");
170 }
171
172 strcat(End,"\n");
173 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
174 exit(100);
175
176 // Dequeue
177 FetchItem *Tmp = Queue;
178 Queue = Queue->Next;
179 delete Tmp;
180 }
181 /*}}}*/
182 // AcqMethod::Configuration - Handle the configuration message /*{{{*/
183 // ---------------------------------------------------------------------
184 /* This parses each configuration entry and puts it into the _config
185 Configuration class. */
186 bool pkgAcqMethod::Configuration(string Message)
187 {
188 ::Configuration &Cnf = *_config;
189
190 const char *I = Message.begin();
191
192 unsigned int Length = strlen("Config-Item");
193 for (; I + Length < Message.end(); I++)
194 {
195 // Not a config item
196 if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
197 continue;
198
199 I += Length + 1;
200
201 for (; I < Message.end() && *I == ' '; I++);
202 const char *Equals = I;
203 for (; Equals < Message.end() && *Equals != '='; Equals++);
204 const char *End = Equals;
205 for (; End < Message.end() && *End != '\n'; End++);
206 if (End == Equals)
207 return false;
208
209 Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
210 I = End;
211 }
212
213 return true;
214 }
215 /*}}}*/
216 // AcqMethod::Run - Run the message engine /*{{{*/
217 // ---------------------------------------------------------------------
218 /* */
219 int pkgAcqMethod::Run(bool Single)
220 {
221 while (1)
222 {
223 // Block if the message queue is empty
224 if (Messages.empty() == true)
225 {
226 if (Single == false)
227 if (WaitFd(STDIN_FILENO) == false)
228 return 0;
229
230 if (ReadMessages(STDIN_FILENO,Messages) == false)
231 return 0;
232 }
233
234 // Single mode exits if the message queue is empty
235 if (Single == true && Messages.empty() == true)
236 return 0;
237
238 string Message = Messages.front();
239 Messages.erase(Messages.begin());
240
241 // Fetch the message number
242 char *End;
243 int Number = strtol(Message.c_str(),&End,10);
244 if (End == Message.c_str())
245 {
246 cerr << "Malformed message!" << endl;
247 return 100;
248 }
249
250 switch (Number)
251 {
252 case 601:
253 if (Configuration(Message) == false)
254 return 100;
255 break;
256
257 case 600:
258 {
259 FetchItem *Tmp = new FetchItem;
260
261 Tmp->Uri = LookupTag(Message,"URI");
262 Tmp->DestFile = LookupTag(Message,"FileName");
263 if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
264 Tmp->LastModified = 0;
265
266 Tmp->Next = 0;
267
268 // Append it to the list
269 FetchItem **I = &Queue;
270 for (; *I != 0; I = &(*I)->Next);
271 *I = Tmp;
272
273 // Notify that this item is to be fetched.
274 if (Fetch(Tmp) == false)
275 Fail();
276
277 break;
278 }
279 }
280 }
281
282 return 0;
283 }
284 /*}}}*/
285 // AcqMethod::Log - Send a log message /*{{{*/
286 // ---------------------------------------------------------------------
287 /* */
288 void pkgAcqMethod::Log(const char *Format,...)
289 {
290 string CurrentURI = "<UNKNOWN>";
291 if (Queue != 0)
292 CurrentURI = Queue->Uri;
293
294 va_list args;
295 va_start(args,Format);
296
297 // sprintf the description
298 char S[1024];
299 unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
300 "Message: ",CurrentURI.c_str());
301
302 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
303 strcat(S,"\n\n");
304
305 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
306 exit(100);
307 }
308 /*}}}*/
309 // AcqMethod::Status - Send a status message /*{{{*/
310 // ---------------------------------------------------------------------
311 /* */
312 void pkgAcqMethod::Status(const char *Format,...)
313 {
314 string CurrentURI = "<UNKNOWN>";
315 if (Queue != 0)
316 CurrentURI = Queue->Uri;
317
318 va_list args;
319 va_start(args,Format);
320
321 // sprintf the description
322 char S[1024];
323 unsigned int Len = snprintf(S,sizeof(S),"102 Status\nURI: %s\n"
324 "Message: ",CurrentURI.c_str());
325
326 vsnprintf(S+Len,sizeof(S)-Len,Format,args);
327 strcat(S,"\n\n");
328
329 if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
330 exit(100);
331 }
332 /*}}}*/
333
334 // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
335 // ---------------------------------------------------------------------
336 /* */
337 pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
338 IMSHit(false), Size(0), ResumePoint(0)
339 {
340 }
341 /*}}}*/
342