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