X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/0a8a80e58374771acc225fe1e08ed8e0fe0016cc..93abae08dbdac43c8ddb4f83c966b16ea7d0107c:/apt-pkg/acquire-worker.cc?ds=inline diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 756b30959..5cd7d6f1e 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-worker.cc,v 1.4 1998/10/22 04:56:40 jgg Exp $ +// $Id: acquire-worker.cc,v 1.34 2001/05/22 04:42:54 jgg Exp $ /* ###################################################################### Acquire Worker @@ -20,23 +20,36 @@ #include #include #include -#include +#include +#include + +#include +#include + +#include #include +#include #include -#include +#include +#include /*}}}*/ +using namespace std; + // Worker::Worker - Constructor for Queue startup /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf) +pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, + pkgAcquireStatus *Log) : Log(Log) { OwnerQ = Q; Config = Cnf; Access = Cnf->Access; CurrentItem = 0; - + TotalSize = 0; + CurrentSize = 0; + Construct(); } /*}}}*/ @@ -49,6 +62,8 @@ pkgAcquire::Worker::Worker(MethodConfig *Cnf) Config = Cnf; Access = Cnf->Access; CurrentItem = 0; + TotalSize = 0; + CurrentSize = 0; Construct(); } @@ -78,9 +93,11 @@ pkgAcquire::Worker::~Worker() if (Process > 0) { - kill(Process,SIGINT); - if (waitpid(Process,0,0) != Process) - _error->Warning("I waited but nothing was there!"); + /* Closing of stdin is the signal to exit and die when the process + indicates it needs cleanup */ + if (Config->NeedsCleanup == false) + kill(Process,SIGINT); + ExecWait(Process,Access.c_str(),true); } } /*}}}*/ @@ -92,7 +109,7 @@ bool pkgAcquire::Worker::Start() // Get the method path string Method = _config->FindDir("Dir::Bin::Methods") + Access; if (FileExists(Method) == false) - return _error->Error("The method driver %s could not be found.",Method.c_str()); + return _error->Error(_("The method driver %s could not be found."),Method.c_str()); if (Debug == true) clog << "Starting method '" << Method << '\'' << endl; @@ -106,24 +123,16 @@ bool pkgAcquire::Worker::Start() close(Pipes[I]); return false; } - + for (int I = 0; I != 4; I++) + SetCloseExec(Pipes[I],true); + // Fork off the process - Process = fork(); - if (Process < 0) - { - cerr << "FATAL -> Failed to fork." << endl; - exit(100); - } - - // Spawn the subprocess + Process = ExecFork(); if (Process == 0) { // Setup the FDs dup2(Pipes[1],STDOUT_FILENO); dup2(Pipes[2],STDIN_FILENO); - dup2(((filebuf *)clog.rdbuf())->fd(),STDERR_FILENO); - for (int I = 0; I != 4; I++) - close(Pipes[I]); SetCloseExec(STDOUT_FILENO,false); SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); @@ -133,7 +142,7 @@ bool pkgAcquire::Worker::Start() Args[1] = 0; execv(Args[0],(char **)Args); cerr << "Failed to exec method " << Args[0] << endl; - exit(100); + _exit(100); } // Fix up our FDs @@ -149,10 +158,11 @@ bool pkgAcquire::Worker::Start() // Read the configuration data if (WaitFd(InFd) == false || ReadMessages() == false) - return _error->Error("Method %s did not start correctly",Method.c_str()); + return _error->Error(_("Method %s did not start correctly"),Method.c_str()); RunMessages(); - SendConfiguration(); + if (OwnerQ != 0) + SendConfiguration(); return true; } @@ -167,7 +177,6 @@ bool pkgAcquire::Worker::ReadMessages() return true; } /*}}}*/ - // Worker::RunMessage - Empty the message queue /*{{{*/ // --------------------------------------------------------------------- /* This takes the messages from the message queue and runs them through @@ -188,6 +197,11 @@ bool pkgAcquire::Worker::RunMessages() if (End == Message.c_str()) return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str()); + string URI = LookupTag(Message,"URI"); + pkgAcquire::Queue::QItem *Itm = 0; + if (URI.empty() == false) + Itm = OwnerQ->FindItem(URI,this); + // Determine the message number and dispatch switch (Number) { @@ -210,19 +224,105 @@ bool pkgAcquire::Worker::RunMessages() // 200 URI Start case 200: - break; + { + if (Itm == 0) + { + _error->Error("Method gave invalid 200 URI Start message"); + break; + } + + CurrentItem = Itm; + CurrentSize = 0; + TotalSize = atoi(LookupTag(Message,"Size","0").c_str()); + ResumePoint = atoi(LookupTag(Message,"Resume-Point","0").c_str()); + Itm->Owner->Start(Message,atoi(LookupTag(Message,"Size","0").c_str())); + + // Display update before completion + if (Log != 0 && Log->MorePulses == true) + Log->Pulse(Itm->Owner->GetOwner()); + + if (Log != 0) + Log->Fetch(*Itm); + + break; + } // 201 URI Done case 201: - break; + { + if (Itm == 0) + { + _error->Error("Method gave invalid 201 URI Done message"); + break; + } + + pkgAcquire::Item *Owner = Itm->Owner; + pkgAcquire::ItemDesc Desc = *Itm; + + // Display update before completion + if (Log != 0 && Log->MorePulses == true) + Log->Pulse(Owner->GetOwner()); + + OwnerQ->ItemDone(Itm); + if (TotalSize != 0 && + (unsigned)atoi(LookupTag(Message,"Size","0").c_str()) != TotalSize) + _error->Warning("Bizarre Error - File size is not what the server reported %s %lu", + LookupTag(Message,"Size","0").c_str(),TotalSize); + + Owner->Done(Message,atoi(LookupTag(Message,"Size","0").c_str()), + LookupTag(Message,"MD5-Hash"),Config); + ItemDone(); + + // Log that we are done + if (Log != 0) + { + if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true || + StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true) + { + /* Hide 'hits' for local only sources - we also manage to + hide gets */ + if (Config->LocalOnly == false) + Log->IMSHit(Desc); + } + else + Log->Done(Desc); + } + break; + } // 400 URI Failure case 400: - break; + { + if (Itm == 0) + { + _error->Error("Method gave invalid 400 URI Failure message"); + break; + } + + // Display update before completion + if (Log != 0 && Log->MorePulses == true) + Log->Pulse(Itm->Owner->GetOwner()); + + pkgAcquire::Item *Owner = Itm->Owner; + pkgAcquire::ItemDesc Desc = *Itm; + OwnerQ->ItemDone(Itm); + Owner->Failed(Message,Config); + ItemDone(); + + if (Log != 0) + Log->Fail(Desc); + + break; + } // 401 General Failure case 401: - _error->Error("Method %s General failure: %s",LookupTag(Message,"Message").c_str()); + _error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str()); + break; + + // 403 Media Change + case 403: + MediaChange(Message); break; } } @@ -240,20 +340,51 @@ bool pkgAcquire::Worker::Capabilities(string Message) Config->Version = LookupTag(Message,"Version"); Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false); - Config->PreScan = StringToBool(LookupTag(Message,"Pre-Scan"),false); Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false); Config->SendConfig = StringToBool(LookupTag(Message,"Send-Config"),false); + Config->LocalOnly = StringToBool(LookupTag(Message,"Local-Only"),false); + Config->NeedsCleanup = StringToBool(LookupTag(Message,"Needs-Cleanup"),false); + Config->Removable = StringToBool(LookupTag(Message,"Removable"),false); // Some debug text if (Debug == true) { clog << "Configured access method " << Config->Access << endl; - clog << "Version:" << Config->Version << " SingleInstance:" << - Config->SingleInstance << " PreScan: " << Config->PreScan << - " Pipeline:" << Config->Pipeline << " SendConfig:" << - Config->SendConfig << endl; + clog << "Version:" << Config->Version << + " SingleInstance:" << Config->SingleInstance << + " Pipeline:" << Config->Pipeline << + " SendConfig:" << Config->SendConfig << + " LocalOnly: " << Config->LocalOnly << + " NeedsCleanup: " << Config->NeedsCleanup << + " Removable: " << Config->Removable << endl; } + return true; +} + /*}}}*/ +// Worker::MediaChange - Request a media change /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgAcquire::Worker::MediaChange(string Message) +{ + if (Log == 0 || Log->MediaChange(LookupTag(Message,"Media"), + LookupTag(Message,"Drive")) == false) + { + char S[300]; + snprintf(S,sizeof(S),"603 Media Changed\nFailed: true\n\n"); + if (Debug == true) + clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl; + OutQueue += S; + OutReady = true; + return true; + } + + char S[300]; + snprintf(S,sizeof(S),"603 Media Changed\n\n"); + if (Debug == true) + clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl; + OutQueue += S; + OutReady = true; return true; } /*}}}*/ @@ -278,7 +409,7 @@ bool pkgAcquire::Worker::SendConfiguration() { if (Top->Value.empty() == false) { - string Line = "Config-Item: " + Top->FullTag() + "="; + string Line = "Config-Item: " + QuoteString(Top->FullTag(),"=\"\n") + "="; Line += QuoteString(Top->Value,"\n") + '\n'; Message += Line; } @@ -332,7 +463,13 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) /* */ bool pkgAcquire::Worker::OutFdReady() { - int Res = write(OutFd,OutQueue.begin(),OutQueue.length()); + int Res; + do + { + Res = write(OutFd,OutQueue.c_str(),OutQueue.length()); + } + while (Res < 0 && errno == EINTR); + if (Res <= 0) return MethodFailure(); @@ -364,9 +501,9 @@ bool pkgAcquire::Worker::InFdReady() read returned -1. */ bool pkgAcquire::Worker::MethodFailure() { - cerr << "Method " << Access << " has died unexpectedly!" << endl; - if (waitpid(Process,0,0) != Process) - _error->Warning("I waited but nothing was there!"); + _error->Error("Method %s has died unexpectedly!",Access.c_str()); + + ExecWait(Process,Access.c_str(),true); Process = -1; close(InFd); close(OutFd); @@ -380,3 +517,32 @@ bool pkgAcquire::Worker::MethodFailure() return false; } /*}}}*/ +// Worker::Pulse - Called periodically /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgAcquire::Worker::Pulse() +{ + if (CurrentItem == 0) + return; + + struct stat Buf; + if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0) + return; + CurrentSize = Buf.st_size; + + // Hmm? Should not happen... + if (CurrentSize > TotalSize && TotalSize != 0) + TotalSize = CurrentSize; +} + /*}}}*/ +// Worker::ItemDone - Called when the current item is finished /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgAcquire::Worker::ItemDone() +{ + CurrentItem = 0; + CurrentSize = 0; + TotalSize = 0; + Status = string(); +} + /*}}}*/