]> git.saurik.com Git - apt.git/blame - apt-pkg/acquire-worker.cc
rework hashsum verification in the acquire system
[apt.git] / apt-pkg / acquire-worker.cc
CommitLineData
0118833a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
24a0d63a 3// $Id: acquire-worker.cc,v 1.34 2001/05/22 04:42:54 jgg Exp $
0118833a
AL
4/* ######################################################################
5
6 Acquire Worker
7
3b5421b4
AL
8 The worker process can startup either as a Configuration prober
9 or as a queue runner. As a configuration prober it only reads the
10 configuration message and
11
0118833a
AL
12 ##################################################################### */
13 /*}}}*/
14// Include Files /*{{{*/
ea542140
DK
15#include <config.h>
16
453b82a3 17#include <apt-pkg/acquire.h>
0118833a 18#include <apt-pkg/acquire-worker.h>
0a8a80e5 19#include <apt-pkg/acquire-item.h>
3b5421b4
AL
20#include <apt-pkg/configuration.h>
21#include <apt-pkg/error.h>
22#include <apt-pkg/fileutl.h>
cdcc6d34 23#include <apt-pkg/strutl.h>
453b82a3 24#include <apt-pkg/hashes.h>
3b5421b4 25
453b82a3
DK
26#include <string>
27#include <vector>
24a0d63a 28#include <iostream>
80a26ed1 29#include <sstream>
ea542140 30
8267fe24 31#include <sys/stat.h>
453b82a3 32#include <stdlib.h>
3b5421b4
AL
33#include <unistd.h>
34#include <signal.h>
542ec555 35#include <stdio.h>
b0db36b1 36#include <errno.h>
359e1c4f
DK
37#include <sys/types.h>
38#include <pwd.h>
39#include <grp.h>
ea542140
DK
40
41#include <apti18n.h>
3b5421b4
AL
42 /*}}}*/
43
24a0d63a
AL
44using namespace std;
45
3b5421b4
AL
46// Worker::Worker - Constructor for Queue startup /*{{{*/
47// ---------------------------------------------------------------------
48/* */
8267fe24
AL
49pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf,
50 pkgAcquireStatus *Log) : Log(Log)
3b5421b4
AL
51{
52 OwnerQ = Q;
0a8a80e5
AL
53 Config = Cnf;
54 Access = Cnf->Access;
55 CurrentItem = 0;
18ef0a78
AL
56 TotalSize = 0;
57 CurrentSize = 0;
448c38bd
DK
58
59 Construct();
3b5421b4
AL
60}
61 /*}}}*/
62// Worker::Worker - Constructor for method config startup /*{{{*/
63// ---------------------------------------------------------------------
64/* */
65pkgAcquire::Worker::Worker(MethodConfig *Cnf)
66{
67 OwnerQ = 0;
68 Config = Cnf;
69 Access = Cnf->Access;
0a8a80e5 70 CurrentItem = 0;
18ef0a78
AL
71 TotalSize = 0;
72 CurrentSize = 0;
448c38bd
DK
73
74 Construct();
3b5421b4
AL
75}
76 /*}}}*/
77// Worker::Construct - Constructor helper /*{{{*/
78// ---------------------------------------------------------------------
79/* */
80void pkgAcquire::Worker::Construct()
81{
0a8a80e5
AL
82 NextQueue = 0;
83 NextAcquire = 0;
3b5421b4
AL
84 Process = -1;
85 InFd = -1;
86 OutFd = -1;
0a8a80e5
AL
87 OutReady = false;
88 InReady = false;
3b5421b4
AL
89 Debug = _config->FindB("Debug::pkgAcquire::Worker",false);
90}
91 /*}}}*/
92// Worker::~Worker - Destructor /*{{{*/
93// ---------------------------------------------------------------------
94/* */
95pkgAcquire::Worker::~Worker()
96{
97 close(InFd);
98 close(OutFd);
99
100 if (Process > 0)
0a8a80e5 101 {
8e5fc8f5
AL
102 /* Closing of stdin is the signal to exit and die when the process
103 indicates it needs cleanup */
104 if (Config->NeedsCleanup == false)
105 kill(Process,SIGINT);
ddc1d8d0 106 ExecWait(Process,Access.c_str(),true);
0a8a80e5 107 }
3b5421b4
AL
108}
109 /*}}}*/
110// Worker::Start - Start the worker process /*{{{*/
111// ---------------------------------------------------------------------
112/* This forks the method and inits the communication channel */
113bool pkgAcquire::Worker::Start()
114{
115 // Get the method path
116 string Method = _config->FindDir("Dir::Bin::Methods") + Access;
117 if (FileExists(Method) == false)
9082a1fc
DK
118 {
119 _error->Error(_("The method driver %s could not be found."),Method.c_str());
120 if (Access == "https")
121 _error->Notice(_("Is the package %s installed?"), "apt-transport-https");
122 return false;
123 }
3b5421b4
AL
124
125 if (Debug == true)
126 clog << "Starting method '" << Method << '\'' << endl;
127
128 // Create the pipes
129 int Pipes[4] = {-1,-1,-1,-1};
130 if (pipe(Pipes) != 0 || pipe(Pipes+2) != 0)
131 {
132 _error->Errno("pipe","Failed to create IPC pipe to subprocess");
133 for (int I = 0; I != 4; I++)
134 close(Pipes[I]);
135 return false;
136 }
8b89e57f 137 for (int I = 0; I != 4; I++)
4490f2de 138 SetCloseExec(Pipes[I],true);
448c38bd 139
3b5421b4 140 // Fork off the process
54676e1a 141 Process = ExecFork();
3b5421b4
AL
142 if (Process == 0)
143 {
144 // Setup the FDs
145 dup2(Pipes[1],STDOUT_FILENO);
146 dup2(Pipes[2],STDIN_FILENO);
3b5421b4 147 SetCloseExec(STDOUT_FILENO,false);
448c38bd 148 SetCloseExec(STDIN_FILENO,false);
3b5421b4 149 SetCloseExec(STDERR_FILENO,false);
448c38bd 150
3b5421b4
AL
151 const char *Args[2];
152 Args[0] = Method.c_str();
153 Args[1] = 0;
154 execv(Args[0],(char **)Args);
155 cerr << "Failed to exec method " << Args[0] << endl;
0dbb95d8 156 _exit(100);
3b5421b4
AL
157 }
158
159 // Fix up our FDs
160 InFd = Pipes[0];
161 OutFd = Pipes[3];
162 SetNonBlock(Pipes[0],true);
163 SetNonBlock(Pipes[3],true);
164 close(Pipes[1]);
165 close(Pipes[2]);
0a8a80e5
AL
166 OutReady = false;
167 InReady = true;
448c38bd 168
3b5421b4
AL
169 // Read the configuration data
170 if (WaitFd(InFd) == false ||
171 ReadMessages() == false)
b2e465d6 172 return _error->Error(_("Method %s did not start correctly"),Method.c_str());
3b5421b4
AL
173
174 RunMessages();
8b89e57f
AL
175 if (OwnerQ != 0)
176 SendConfiguration();
448c38bd 177
3b5421b4
AL
178 return true;
179}
180 /*}}}*/
181// Worker::ReadMessages - Read all pending messages into the list /*{{{*/
182// ---------------------------------------------------------------------
0a8a80e5 183/* */
3b5421b4
AL
184bool pkgAcquire::Worker::ReadMessages()
185{
0a8a80e5
AL
186 if (::ReadMessages(InFd,MessageQueue) == false)
187 return MethodFailure();
3b5421b4
AL
188 return true;
189}
190 /*}}}*/
3b5421b4
AL
191// Worker::RunMessage - Empty the message queue /*{{{*/
192// ---------------------------------------------------------------------
193/* This takes the messages from the message queue and runs them through
194 the parsers in order. */
195bool pkgAcquire::Worker::RunMessages()
196{
197 while (MessageQueue.empty() == false)
198 {
199 string Message = MessageQueue.front();
200 MessageQueue.erase(MessageQueue.begin());
0a8a80e5
AL
201
202 if (Debug == true)
203 clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl;
448c38bd 204
3b5421b4
AL
205 // Fetch the message number
206 char *End;
207 int Number = strtol(Message.c_str(),&End,10);
208 if (End == Message.c_str())
209 return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str());
210
c88edf1d
AL
211 string URI = LookupTag(Message,"URI");
212 pkgAcquire::Queue::QItem *Itm = 0;
213 if (URI.empty() == false)
214 Itm = OwnerQ->FindItem(URI,this);
196fd136
MV
215
216 // update used mirror
217 string UsedMirror = LookupTag(Message,"UsedMirror", "");
448c38bd 218 if (!UsedMirror.empty() &&
196fd136 219 Itm &&
448c38bd 220 Itm->Description.find(" ") != string::npos)
196fd136
MV
221 {
222 Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror);
223 // FIXME: will we need this as well?
224 //Itm->ShortDesc = UsedMirror;
225 }
448c38bd 226
3b5421b4
AL
227 // Determine the message number and dispatch
228 switch (Number)
229 {
0a8a80e5 230 // 100 Capabilities
3b5421b4
AL
231 case 100:
232 if (Capabilities(Message) == false)
233 return _error->Error("Unable to process Capabilities message from %s",Access.c_str());
234 break;
448c38bd 235
0a8a80e5
AL
236 // 101 Log
237 case 101:
238 if (Debug == true)
239 clog << " <- (log) " << LookupTag(Message,"Message") << endl;
240 break;
448c38bd 241
0a8a80e5
AL
242 // 102 Status
243 case 102:
244 Status = LookupTag(Message,"Message");
245 break;
448c38bd 246
15d7e515
MV
247 // 103 Redirect
248 case 103:
249 {
250 if (Itm == 0)
251 {
252 _error->Error("Method gave invalid 103 Redirect message");
253 break;
254 }
448c38bd 255
15d7e515
MV
256 string NewURI = LookupTag(Message,"New-URI",URI.c_str());
257 Itm->URI = NewURI;
5674f6b3
RG
258
259 ItemDone();
260
261 pkgAcquire::Item *Owner = Itm->Owner;
262 pkgAcquire::ItemDesc Desc = *Itm;
263
264 // Change the status so that it can be dequeued
265 Owner->Status = pkgAcquire::Item::StatIdle;
266 // Mark the item as done (taking care of all queues)
267 // and then put it in the main queue again
268 OwnerQ->ItemDone(Itm);
269 OwnerQ->Owner->Enqueue(Desc);
270
271 if (Log != 0)
272 Log->Done(Desc);
15d7e515
MV
273 break;
274 }
448c38bd 275
0a8a80e5
AL
276 // 200 URI Start
277 case 200:
c88edf1d
AL
278 {
279 if (Itm == 0)
280 {
93bf083d 281 _error->Error("Method gave invalid 200 URI Start message");
c88edf1d
AL
282 break;
283 }
448c38bd 284
c88edf1d
AL
285 CurrentItem = Itm;
286 CurrentSize = 0;
650faab0
DK
287 TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
288 ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10);
448c38bd 289 Itm->Owner->Start(Message, TotalSize);
8b75eb1c 290
c5ccf175
AL
291 // Display update before completion
292 if (Log != 0 && Log->MorePulses == true)
293 Log->Pulse(Itm->Owner->GetOwner());
448c38bd 294
8267fe24
AL
295 if (Log != 0)
296 Log->Fetch(*Itm);
297
c88edf1d
AL
298 break;
299 }
448c38bd 300
0a8a80e5
AL
301 // 201 URI Done
302 case 201:
c88edf1d
AL
303 {
304 if (Itm == 0)
305 {
93bf083d 306 _error->Error("Method gave invalid 201 URI Done message");
c88edf1d
AL
307 break;
308 }
448c38bd 309
bfd22fc0 310 pkgAcquire::Item *Owner = Itm->Owner;
8267fe24 311 pkgAcquire::ItemDesc Desc = *Itm;
359e1c4f
DK
312
313 if (RealFileExists(Owner->DestFile))
314 ChangeOwnerAndPermissionOfFile("201::URIDone", Owner->DestFile.c_str(), "root", "root", 0644);
315
c5ccf175
AL
316 // Display update before completion
317 if (Log != 0 && Log->MorePulses == true)
318 Log->Pulse(Owner->GetOwner());
448c38bd 319
be4401bf 320 OwnerQ->ItemDone(Itm);
448c38bd
DK
321
322 HashStringList const ExpectedHashes = Owner->GetExpectedHashes();
323 // see if we got hashes to verify
20801f61 324 HashStringList ReceivedHashes;
8eafc759 325 for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
8a8feb29 326 {
8eafc759 327 std::string const tagname = std::string(*type) + "-Hash";
b3501edb
DK
328 std::string const hashsum = LookupTag(Message, tagname.c_str());
329 if (hashsum.empty() == false)
8eafc759 330 ReceivedHashes.push_back(HashString(*type, hashsum));
b3501edb 331 }
448c38bd
DK
332 // not all methods always sent Hashes our way
333 if (ExpectedHashes.usable() == true && ReceivedHashes.usable() == false)
334 {
335 std::string const filename = LookupTag(Message, "Filename", Owner->DestFile.c_str());
336 if (filename.empty() == false && RealFileExists(filename))
337 {
338 Hashes calc(ExpectedHashes);
339 FileFd file(filename, FileFd::ReadOnly, FileFd::None);
340 calc.AddFD(file);
341 ReceivedHashes = calc.GetHashStringList();
342 }
343 }
b3501edb
DK
344
345 if(_config->FindB("Debug::pkgAcquire::Auth", false) == true)
346 {
347 std::clog << "201 URI Done: " << Owner->DescURI() << endl
20801f61
DK
348 << "ReceivedHash:" << endl;
349 for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs)
b3501edb
DK
350 std::clog << "\t- " << hs->toStr() << std::endl;
351 std::clog << "ExpectedHash:" << endl;
448c38bd 352 for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs)
b3501edb
DK
353 std::clog << "\t- " << hs->toStr() << std::endl;
354 std::clog << endl;
8a8feb29 355 }
b3501edb 356
448c38bd
DK
357 // decide if what we got is what we expected
358 bool consideredOkay = false;
359 bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) ||
360 StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false);
361 if (ExpectedHashes.usable())
8267fe24 362 {
448c38bd 363 if (ReceivedHashes.usable() == false)
c46824ce 364 {
448c38bd
DK
365 /* IMS-Hits can't be checked here as we will have uncompressed file,
366 but the hashes for the compressed file. What we have was good through
367 so all we have to ensure later is that we are not stalled. */
368 consideredOkay = isIMSHit;
369 }
370 else if (ReceivedHashes == ExpectedHashes)
371 consideredOkay = true;
8267fe24 372 else
448c38bd
DK
373 consideredOkay = false;
374
375 }
376 else if (Owner->HashesRequired() == true)
377 consideredOkay = false;
378 else
379 consideredOkay = true;
380
381 if (consideredOkay == true)
382 {
383 Owner->Done(Message, ReceivedHashes, Config);
384 ItemDone();
385
386 // Log that we are done
387 if (Log != 0)
388 {
389 if (isIMSHit)
390 {
391 /* Hide 'hits' for local only sources - we also manage to
392 hide gets */
393 if (Config->LocalOnly == false)
394 Log->IMSHit(Desc);
395 }
396 else
397 Log->Done(Desc);
398 }
399 }
400 else
401 {
402 Owner->Status = pkgAcquire::Item::StatAuthError;
403 Owner->Failed(Message,Config);
404 ItemDone();
405
406 if (Log != 0)
407 Log->Fail(Desc);
18ef0a78 408 }
c88edf1d 409 break;
448c38bd
DK
410 }
411
0a8a80e5
AL
412 // 400 URI Failure
413 case 400:
c88edf1d
AL
414 {
415 if (Itm == 0)
416 {
5684f71f
DK
417 std::string const msg = LookupTag(Message,"Message");
418 _error->Error("Method gave invalid 400 URI Failure message: %s", msg.c_str());
c88edf1d
AL
419 break;
420 }
421
c5ccf175
AL
422 // Display update before completion
423 if (Log != 0 && Log->MorePulses == true)
424 Log->Pulse(Itm->Owner->GetOwner());
359e1c4f 425
bfd22fc0 426 pkgAcquire::Item *Owner = Itm->Owner;
8267fe24 427 pkgAcquire::ItemDesc Desc = *Itm;
359e1c4f
DK
428
429 if (RealFileExists(Owner->DestFile))
430 ChangeOwnerAndPermissionOfFile("400::URIFailure", Owner->DestFile.c_str(), "root", "root", 0644);
431
c88edf1d 432 OwnerQ->ItemDone(Itm);
7e5f33eb
MV
433
434 // set some status
435 if(LookupTag(Message,"FailReason") == "Timeout" ||
436 LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
f0983ff2 437 LookupTag(Message,"FailReason") == "ResolveFailure" ||
7e5f33eb
MV
438 LookupTag(Message,"FailReason") == "ConnectionRefused")
439 Owner->Status = pkgAcquire::Item::StatTransientNetworkError;
440
7d8afa39 441 Owner->Failed(Message,Config);
8267fe24 442 ItemDone();
7d8afa39 443
8267fe24
AL
444 if (Log != 0)
445 Log->Fail(Desc);
7d8afa39 446
c88edf1d 447 break;
448c38bd
DK
448 }
449
0a8a80e5
AL
450 // 401 General Failure
451 case 401:
b2e465d6 452 _error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str());
0a8a80e5 453 break;
448c38bd 454
542ec555
AL
455 // 403 Media Change
456 case 403:
448c38bd 457 MediaChange(Message);
542ec555 458 break;
448c38bd 459 }
3b5421b4
AL
460 }
461 return true;
462}
463 /*}}}*/
464// Worker::Capabilities - 100 Capabilities handler /*{{{*/
465// ---------------------------------------------------------------------
466/* This parses the capabilities message and dumps it into the configuration
467 structure. */
468bool pkgAcquire::Worker::Capabilities(string Message)
469{
470 if (Config == 0)
471 return true;
448c38bd 472
3b5421b4
AL
473 Config->Version = LookupTag(Message,"Version");
474 Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false);
0a8a80e5
AL
475 Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false);
476 Config->SendConfig = StringToBool(LookupTag(Message,"Send-Config"),false);
e331f6ed 477 Config->LocalOnly = StringToBool(LookupTag(Message,"Local-Only"),false);
8e5fc8f5 478 Config->NeedsCleanup = StringToBool(LookupTag(Message,"Needs-Cleanup"),false);
459681d3 479 Config->Removable = StringToBool(LookupTag(Message,"Removable"),false);
3b5421b4
AL
480
481 // Some debug text
482 if (Debug == true)
483 {
484 clog << "Configured access method " << Config->Access << endl;
459681d3
AL
485 clog << "Version:" << Config->Version <<
486 " SingleInstance:" << Config->SingleInstance <<
448c38bd
DK
487 " Pipeline:" << Config->Pipeline <<
488 " SendConfig:" << Config->SendConfig <<
489 " LocalOnly: " << Config->LocalOnly <<
490 " NeedsCleanup: " << Config->NeedsCleanup <<
459681d3 491 " Removable: " << Config->Removable << endl;
3b5421b4 492 }
448c38bd 493
542ec555
AL
494 return true;
495}
496 /*}}}*/
497// Worker::MediaChange - Request a media change /*{{{*/
498// ---------------------------------------------------------------------
499/* */
500bool pkgAcquire::Worker::MediaChange(string Message)
501{
80a26ed1 502 int status_fd = _config->FindI("APT::Status-Fd",-1);
448c38bd 503 if(status_fd > 0)
80a26ed1
MV
504 {
505 string Media = LookupTag(Message,"Media");
448c38bd 506 string Drive = LookupTag(Message,"Drive");
80a26ed1 507 ostringstream msg,status;
1a82c63e
MV
508 ioprintf(msg,_("Please insert the disc labeled: "
509 "'%s' "
510 "in the drive '%s' and press enter."),
511 Media.c_str(),Drive.c_str());
80a26ed1 512 status << "media-change: " // message
1a82c63e
MV
513 << Media << ":" // media
514 << Drive << ":" // drive
515 << msg.str() // l10n message
80a26ed1 516 << endl;
31bda500
DK
517
518 std::string const dlstatus = status.str();
d68d65ad 519 FileFd::Write(status_fd, dlstatus.c_str(), dlstatus.size());
80a26ed1
MV
520 }
521
542ec555
AL
522 if (Log == 0 || Log->MediaChange(LookupTag(Message,"Media"),
523 LookupTag(Message,"Drive")) == false)
524 {
525 char S[300];
96bc43c4 526 snprintf(S,sizeof(S),"603 Media Changed\nFailed: true\n\n");
542ec555
AL
527 if (Debug == true)
528 clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
529 OutQueue += S;
530 OutReady = true;
531 return true;
532 }
533
534 char S[300];
96bc43c4 535 snprintf(S,sizeof(S),"603 Media Changed\n\n");
542ec555
AL
536 if (Debug == true)
537 clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
538 OutQueue += S;
539 OutReady = true;
3b5421b4
AL
540 return true;
541}
0118833a 542 /*}}}*/
0a8a80e5
AL
543// Worker::SendConfiguration - Send the config to the method /*{{{*/
544// ---------------------------------------------------------------------
545/* */
546bool pkgAcquire::Worker::SendConfiguration()
547{
548 if (Config->SendConfig == false)
549 return true;
550
551 if (OutFd == -1)
552 return false;
0a8a80e5 553
d280d03a 554 /* Write out all of the configuration directives by walking the
0a8a80e5 555 configuration tree */
d280d03a
DK
556 std::ostringstream Message;
557 Message << "601 Configuration\n";
558 _config->Dump(Message, NULL, "Config-Item: %F=%V\n", false);
559 Message << '\n';
0a8a80e5
AL
560
561 if (Debug == true)
d280d03a
DK
562 clog << " -> " << Access << ':' << QuoteString(Message.str(),"\n") << endl;
563 OutQueue += Message.str();
564 OutReady = true;
565
0a8a80e5
AL
566 return true;
567}
568 /*}}}*/
569// Worker::QueueItem - Add an item to the outbound queue /*{{{*/
570// ---------------------------------------------------------------------
571/* Send a URI Acquire message to the method */
572bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
573{
574 if (OutFd == -1)
575 return false;
448c38bd 576
0a8a80e5
AL
577 string Message = "600 URI Acquire\n";
578 Message.reserve(300);
579 Message += "URI: " + Item->URI;
580 Message += "\nFilename: " + Item->Owner->DestFile;
448c38bd 581 HashStringList const hsl = Item->Owner->GetExpectedHashes();
d003a557
DK
582 for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
583 Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
c48eea97
MV
584 if(Item->Owner->FileSize > 0)
585 {
586 string MaximumSize;
587 strprintf(MaximumSize, "%llu", Item->Owner->FileSize);
588 Message += "\nMaximum-Size: " + MaximumSize;
589 }
0a8a80e5
AL
590 Message += Item->Owner->Custom600Headers();
591 Message += "\n\n";
359e1c4f
DK
592
593 if (RealFileExists(Item->Owner->DestFile))
594 {
595 std::string SandboxUser = _config->Find("APT::Sandbox::User");
596 ChangeOwnerAndPermissionOfFile("Item::QueueURI", Item->Owner->DestFile.c_str(),
597 SandboxUser.c_str(), "root", 0600);
598 }
599
0a8a80e5
AL
600 if (Debug == true)
601 clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl;
602 OutQueue += Message;
603 OutReady = true;
448c38bd 604
0a8a80e5
AL
605 return true;
606}
607 /*}}}*/
608// Worker::OutFdRead - Out bound FD is ready /*{{{*/
609// ---------------------------------------------------------------------
610/* */
611bool pkgAcquire::Worker::OutFdReady()
612{
ee7af1bd
YY
613 int Res;
614 do
615 {
616 Res = write(OutFd,OutQueue.c_str(),OutQueue.length());
617 }
618 while (Res < 0 && errno == EINTR);
619
620 if (Res <= 0)
0a8a80e5 621 return MethodFailure();
ee7af1bd
YY
622
623 OutQueue.erase(0,Res);
0a8a80e5
AL
624 if (OutQueue.empty() == true)
625 OutReady = false;
448c38bd 626
0a8a80e5
AL
627 return true;
628}
629 /*}}}*/
630// Worker::InFdRead - In bound FD is ready /*{{{*/
631// ---------------------------------------------------------------------
632/* */
633bool pkgAcquire::Worker::InFdReady()
634{
635 if (ReadMessages() == false)
636 return false;
637 RunMessages();
638 return true;
639}
640 /*}}}*/
641// Worker::MethodFailure - Called when the method fails /*{{{*/
642// ---------------------------------------------------------------------
1e3f4083 643/* This is called when the method is believed to have failed, probably because
0a8a80e5
AL
644 read returned -1. */
645bool pkgAcquire::Worker::MethodFailure()
646{
76d97c26 647 _error->Error("Method %s has died unexpectedly!",Access.c_str());
448c38bd 648
ab7f4d7c
MV
649 // do not reap the child here to show meaningfull error to the user
650 ExecWait(Process,Access.c_str(),false);
0a8a80e5
AL
651 Process = -1;
652 close(InFd);
653 close(OutFd);
654 InFd = -1;
655 OutFd = -1;
656 OutReady = false;
657 InReady = false;
658 OutQueue = string();
659 MessageQueue.erase(MessageQueue.begin(),MessageQueue.end());
448c38bd 660
0a8a80e5
AL
661 return false;
662}
663 /*}}}*/
448c38bd 664// Worker::Pulse - Called periodically /*{{{*/
8267fe24
AL
665// ---------------------------------------------------------------------
666/* */
667void pkgAcquire::Worker::Pulse()
668{
669 if (CurrentItem == 0)
670 return;
448c38bd 671
8267fe24
AL
672 struct stat Buf;
673 if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
674 return;
675 CurrentSize = Buf.st_size;
676}
677 /*}}}*/
678// Worker::ItemDone - Called when the current item is finished /*{{{*/
679// ---------------------------------------------------------------------
680/* */
681void pkgAcquire::Worker::ItemDone()
682{
683 CurrentItem = 0;
684 CurrentSize = 0;
685 TotalSize = 0;
686 Status = string();
687}
688 /*}}}*/