|
|
@ -26,7 +26,6 @@ |
|
|
|
#include <string> |
|
|
|
#include <vector> |
|
|
|
#include <iostream> |
|
|
|
#include <sstream> |
|
|
|
|
|
|
|
#include <sys/stat.h> |
|
|
|
#include <stdlib.h> |
|
|
@ -34,9 +33,7 @@ |
|
|
|
#include <signal.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <sys/types.h> |
|
|
|
#include <pwd.h> |
|
|
|
#include <grp.h> |
|
|
|
#include <sstream> |
|
|
|
|
|
|
|
#include <apti18n.h> |
|
|
|
/*}}}*/ |
|
|
@ -47,7 +44,7 @@ using namespace std; |
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */ |
|
|
|
pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, |
|
|
|
pkgAcquireStatus *Log) : Log(Log) |
|
|
|
pkgAcquireStatus *log) : d(NULL), Log(log) |
|
|
|
{ |
|
|
|
OwnerQ = Q; |
|
|
|
Config = Cnf; |
|
|
@ -55,23 +52,18 @@ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, |
|
|
|
CurrentItem = 0; |
|
|
|
TotalSize = 0; |
|
|
|
CurrentSize = 0; |
|
|
|
|
|
|
|
Construct(); |
|
|
|
|
|
|
|
Construct(); |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
// Worker::Worker - Constructor for method config startup /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */ |
|
|
|
pkgAcquire::Worker::Worker(MethodConfig *Cnf) |
|
|
|
pkgAcquire::Worker::Worker(MethodConfig *Cnf) : d(NULL), OwnerQ(NULL), Config(Cnf), |
|
|
|
Access(Cnf->Access), CurrentItem(NULL), |
|
|
|
CurrentSize(0), TotalSize(0) |
|
|
|
{ |
|
|
|
OwnerQ = 0; |
|
|
|
Config = Cnf; |
|
|
|
Access = Cnf->Access; |
|
|
|
CurrentItem = 0; |
|
|
|
TotalSize = 0; |
|
|
|
CurrentSize = 0; |
|
|
|
|
|
|
|
Construct(); |
|
|
|
Construct(); |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
// Worker::Construct - Constructor helper /*{{{*/
|
|
|
@ -136,7 +128,7 @@ bool pkgAcquire::Worker::Start() |
|
|
|
} |
|
|
|
for (int I = 0; I != 4; I++) |
|
|
|
SetCloseExec(Pipes[I],true); |
|
|
|
|
|
|
|
|
|
|
|
// Fork off the process
|
|
|
|
Process = ExecFork(); |
|
|
|
if (Process == 0) |
|
|
@ -145,9 +137,9 @@ bool pkgAcquire::Worker::Start() |
|
|
|
dup2(Pipes[1],STDOUT_FILENO); |
|
|
|
dup2(Pipes[2],STDIN_FILENO); |
|
|
|
SetCloseExec(STDOUT_FILENO,false); |
|
|
|
SetCloseExec(STDIN_FILENO,false); |
|
|
|
SetCloseExec(STDIN_FILENO,false); |
|
|
|
SetCloseExec(STDERR_FILENO,false); |
|
|
|
|
|
|
|
|
|
|
|
const char *Args[2]; |
|
|
|
Args[0] = Method.c_str(); |
|
|
|
Args[1] = 0; |
|
|
@ -165,7 +157,7 @@ bool pkgAcquire::Worker::Start() |
|
|
|
close(Pipes[2]); |
|
|
|
OutReady = false; |
|
|
|
InReady = true; |
|
|
|
|
|
|
|
|
|
|
|
// Read the configuration data
|
|
|
|
if (WaitFd(InFd) == false || |
|
|
|
ReadMessages() == false) |
|
|
@ -174,7 +166,7 @@ bool pkgAcquire::Worker::Start() |
|
|
|
RunMessages(); |
|
|
|
if (OwnerQ != 0) |
|
|
|
SendConfiguration(); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
@ -201,7 +193,7 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
|
|
|
|
if (Debug == true) |
|
|
|
clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl; |
|
|
|
|
|
|
|
|
|
|
|
// Fetch the message number
|
|
|
|
char *End; |
|
|
|
int Number = strtol(Message.c_str(),&End,10); |
|
|
@ -209,21 +201,24 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
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; |
|
|
|
pkgAcquire::Queue::QItem *Itm = NULL; |
|
|
|
if (URI.empty() == false) |
|
|
|
Itm = OwnerQ->FindItem(URI,this); |
|
|
|
|
|
|
|
// update used mirror
|
|
|
|
string UsedMirror = LookupTag(Message,"UsedMirror", ""); |
|
|
|
if (!UsedMirror.empty() && |
|
|
|
Itm && |
|
|
|
Itm->Description.find(" ") != string::npos) |
|
|
|
if (Itm != NULL) |
|
|
|
{ |
|
|
|
Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); |
|
|
|
// FIXME: will we need this as well?
|
|
|
|
//Itm->ShortDesc = UsedMirror;
|
|
|
|
// update used mirror
|
|
|
|
string UsedMirror = LookupTag(Message,"UsedMirror", ""); |
|
|
|
if (UsedMirror.empty() == false) |
|
|
|
{ |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
(*O)->UsedMirror = UsedMirror; |
|
|
|
|
|
|
|
if (Itm->Description.find(" ") != string::npos) |
|
|
|
Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Determine the message number and dispatch
|
|
|
|
switch (Number) |
|
|
|
{ |
|
|
@ -232,18 +227,18 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
if (Capabilities(Message) == false) |
|
|
|
return _error->Error("Unable to process Capabilities message from %s",Access.c_str()); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// 101 Log
|
|
|
|
case 101: |
|
|
|
if (Debug == true) |
|
|
|
clog << " <- (log) " << LookupTag(Message,"Message") << endl; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// 102 Status
|
|
|
|
case 102: |
|
|
|
Status = LookupTag(Message,"Message"); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// 103 Redirect
|
|
|
|
case 103: |
|
|
|
{ |
|
|
@ -252,27 +247,49 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
_error->Error("Method gave invalid 103 Redirect message"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
string NewURI = LookupTag(Message,"New-URI",URI.c_str()); |
|
|
|
|
|
|
|
std::string const NewURI = LookupTag(Message,"New-URI",URI.c_str()); |
|
|
|
Itm->URI = NewURI; |
|
|
|
|
|
|
|
ItemDone(); |
|
|
|
|
|
|
|
pkgAcquire::Item *Owner = Itm->Owner; |
|
|
|
pkgAcquire::ItemDesc Desc = *Itm; |
|
|
|
|
|
|
|
// Change the status so that it can be dequeued
|
|
|
|
Owner->Status = pkgAcquire::Item::StatIdle; |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
(*O)->Status = pkgAcquire::Item::StatIdle; |
|
|
|
// Mark the item as done (taking care of all queues)
|
|
|
|
// and then put it in the main queue again
|
|
|
|
std::vector<Item*> const ItmOwners = Itm->Owners; |
|
|
|
OwnerQ->ItemDone(Itm); |
|
|
|
OwnerQ->Owner->Enqueue(Desc); |
|
|
|
|
|
|
|
if (Log != 0) |
|
|
|
Log->Done(Desc); |
|
|
|
Itm = NULL; |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) |
|
|
|
{ |
|
|
|
pkgAcquire::Item *Owner = *O; |
|
|
|
pkgAcquire::ItemDesc &desc = Owner->GetItemDesc(); |
|
|
|
// if we change site, treat it as a mirror change
|
|
|
|
if (URI::SiteOnly(NewURI) != URI::SiteOnly(desc.URI)) |
|
|
|
{ |
|
|
|
std::string const OldSite = desc.Description.substr(0, desc.Description.find(" ")); |
|
|
|
if (likely(APT::String::Startswith(desc.URI, OldSite))) |
|
|
|
{ |
|
|
|
std::string const OldExtra = desc.URI.substr(OldSite.length() + 1); |
|
|
|
if (likely(APT::String::Endswith(NewURI, OldExtra))) |
|
|
|
{ |
|
|
|
std::string const NewSite = NewURI.substr(0, NewURI.length() - OldExtra.length()); |
|
|
|
Owner->UsedMirror = URI::ArchiveOnly(NewSite); |
|
|
|
if (desc.Description.find(" ") != string::npos) |
|
|
|
desc.Description.replace(0, desc.Description.find(" "), Owner->UsedMirror); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
desc.URI = NewURI; |
|
|
|
OwnerQ->Owner->Enqueue(desc); |
|
|
|
|
|
|
|
if (Log != 0) |
|
|
|
Log->Done(desc); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 200 URI Start
|
|
|
|
case 200: |
|
|
|
{ |
|
|
@ -281,23 +298,27 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
_error->Error("Method gave invalid 200 URI Start message"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CurrentItem = Itm; |
|
|
|
CurrentSize = 0; |
|
|
|
TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); |
|
|
|
ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10); |
|
|
|
Itm->Owner->Start(Message,strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10)); |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
{ |
|
|
|
(*O)->Start(Message, TotalSize); |
|
|
|
|
|
|
|
// Display update before completion
|
|
|
|
if (Log != 0 && Log->MorePulses == true) |
|
|
|
Log->Pulse(Itm->Owner->GetOwner()); |
|
|
|
|
|
|
|
if (Log != 0) |
|
|
|
Log->Fetch(*Itm); |
|
|
|
// Display update before completion
|
|
|
|
if (Log != 0) |
|
|
|
{ |
|
|
|
if (Log->MorePulses == true) |
|
|
|
Log->Pulse((*O)->GetOwner()); |
|
|
|
Log->Fetch((*O)->GetItemDesc()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 201 URI Done
|
|
|
|
case 201: |
|
|
|
{ |
|
|
@ -306,72 +327,114 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
_error->Error("Method gave invalid 201 URI Done message"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
pkgAcquire::Item *Owner = Itm->Owner; |
|
|
|
pkgAcquire::ItemDesc Desc = *Itm; |
|
|
|
|
|
|
|
if (RealFileExists(Owner->DestFile)) |
|
|
|
ChangeOwnerAndPermissionOfFile("201::URIDone", Owner->DestFile.c_str(), "root", "root", 0644); |
|
|
|
PrepareFiles("201::URIDone", Itm); |
|
|
|
|
|
|
|
// Display update before completion
|
|
|
|
if (Log != 0 && Log->MorePulses == true) |
|
|
|
Log->Pulse(Owner->GetOwner()); |
|
|
|
|
|
|
|
OwnerQ->ItemDone(Itm); |
|
|
|
unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); |
|
|
|
bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || |
|
|
|
StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); |
|
|
|
// Using the https method the server might return 200, but the
|
|
|
|
// If-Modified-Since condition is not satsified, libcurl will
|
|
|
|
// discard the download. In this case, however, TotalSize will be
|
|
|
|
// set to the actual size of the file, while ServerSize will be set
|
|
|
|
// to 0. Therefore, if the item is marked as a hit and the
|
|
|
|
// downloaded size (ServerSize) is 0, we ignore TotalSize.
|
|
|
|
if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize) |
|
|
|
_error->Warning("Size of file %s is not what the server reported %s %llu", |
|
|
|
Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); |
|
|
|
|
|
|
|
// see if there is a hash to verify
|
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
Log->Pulse((*O)->GetOwner()); |
|
|
|
|
|
|
|
std::string const filename = LookupTag(Message, "Filename", Itm->Owner->DestFile.c_str()); |
|
|
|
HashStringList ReceivedHashes; |
|
|
|
for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) |
|
|
|
{ |
|
|
|
std::string const tagname = std::string(*type) + "-Hash"; |
|
|
|
std::string const hashsum = LookupTag(Message, tagname.c_str()); |
|
|
|
if (hashsum.empty() == false) |
|
|
|
ReceivedHashes.push_back(HashString(*type, hashsum)); |
|
|
|
// see if we got hashes to verify
|
|
|
|
for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) |
|
|
|
{ |
|
|
|
std::string const tagname = std::string(*type) + "-Hash"; |
|
|
|
std::string const hashsum = LookupTag(Message, tagname.c_str()); |
|
|
|
if (hashsum.empty() == false) |
|
|
|
ReceivedHashes.push_back(HashString(*type, hashsum)); |
|
|
|
} |
|
|
|
// not all methods always sent Hashes our way
|
|
|
|
if (ReceivedHashes.usable() == false) |
|
|
|
{ |
|
|
|
HashStringList const ExpectedHashes = Itm->GetExpectedHashes(); |
|
|
|
if (ExpectedHashes.usable() == true && RealFileExists(filename)) |
|
|
|
{ |
|
|
|
Hashes calc(ExpectedHashes); |
|
|
|
FileFd file(filename, FileFd::ReadOnly, FileFd::None); |
|
|
|
calc.AddFD(file); |
|
|
|
ReceivedHashes = calc.GetHashStringList(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) |
|
|
|
{ |
|
|
|
std::clog << "201 URI Done: " << Owner->DescURI() << endl |
|
|
|
<< "ReceivedHash:" << endl; |
|
|
|
for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) |
|
|
|
std::clog << "\t- " << hs->toStr() << std::endl; |
|
|
|
std::clog << "ExpectedHash:" << endl; |
|
|
|
HashStringList expectedHashes = Owner->HashSums(); |
|
|
|
for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) |
|
|
|
std::clog << "\t- " << hs->toStr() << std::endl; |
|
|
|
std::clog << endl; |
|
|
|
} |
|
|
|
Owner->Done(Message, ServerSize, ReceivedHashes, Config); |
|
|
|
ItemDone(); |
|
|
|
// only local files can refer other filenames and counting them as fetched would be unfair
|
|
|
|
if (Log != NULL && filename != Itm->Owner->DestFile) |
|
|
|
Log->Fetched(ReceivedHashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); |
|
|
|
|
|
|
|
std::vector<Item*> const ItmOwners = Itm->Owners; |
|
|
|
OwnerQ->ItemDone(Itm); |
|
|
|
Itm = NULL; |
|
|
|
|
|
|
|
// Log that we are done
|
|
|
|
if (Log != 0) |
|
|
|
bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || |
|
|
|
StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) |
|
|
|
{ |
|
|
|
if (isHit) |
|
|
|
pkgAcquire::Item * const Owner = *O; |
|
|
|
HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); |
|
|
|
if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) |
|
|
|
{ |
|
|
|
std::clog << "201 URI Done: " << Owner->DescURI() << endl |
|
|
|
<< "ReceivedHash:" << endl; |
|
|
|
for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) |
|
|
|
std::clog << "\t- " << hs->toStr() << std::endl; |
|
|
|
std::clog << "ExpectedHash:" << endl; |
|
|
|
for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) |
|
|
|
std::clog << "\t- " << hs->toStr() << std::endl; |
|
|
|
std::clog << endl; |
|
|
|
} |
|
|
|
|
|
|
|
// decide if what we got is what we expected
|
|
|
|
bool consideredOkay = false; |
|
|
|
if (ExpectedHashes.usable()) |
|
|
|
{ |
|
|
|
/* Hide 'hits' for local only sources - we also manage to
|
|
|
|
hide gets */ |
|
|
|
if (Config->LocalOnly == false) |
|
|
|
Log->IMSHit(Desc); |
|
|
|
} |
|
|
|
if (ReceivedHashes.usable() == false) |
|
|
|
{ |
|
|
|
/* IMS-Hits can't be checked here as we will have uncompressed file,
|
|
|
|
but the hashes for the compressed file. What we have was good through |
|
|
|
so all we have to ensure later is that we are not stalled. */ |
|
|
|
consideredOkay = isIMSHit; |
|
|
|
} |
|
|
|
else if (ReceivedHashes == ExpectedHashes) |
|
|
|
consideredOkay = true; |
|
|
|
else |
|
|
|
consideredOkay = false; |
|
|
|
|
|
|
|
} |
|
|
|
else if (Owner->HashesRequired() == true) |
|
|
|
consideredOkay = false; |
|
|
|
else |
|
|
|
Log->Done(Desc); |
|
|
|
consideredOkay = true; |
|
|
|
|
|
|
|
if (consideredOkay == true) |
|
|
|
consideredOkay = Owner->VerifyDone(Message, Config); |
|
|
|
else // hashsum mismatch
|
|
|
|
Owner->Status = pkgAcquire::Item::StatAuthError; |
|
|
|
|
|
|
|
if (consideredOkay == true) |
|
|
|
{ |
|
|
|
Owner->Done(Message, ReceivedHashes, Config); |
|
|
|
if (Log != 0) |
|
|
|
{ |
|
|
|
if (isIMSHit) |
|
|
|
Log->IMSHit(Owner->GetItemDesc()); |
|
|
|
else |
|
|
|
Log->Done(Owner->GetItemDesc()); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Owner->Failed(Message,Config); |
|
|
|
if (Log != 0) |
|
|
|
Log->Fail(Owner->GetItemDesc()); |
|
|
|
} |
|
|
|
} |
|
|
|
ItemDone(); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 400 URI Failure
|
|
|
|
case 400: |
|
|
|
{ |
|
|
@ -382,44 +445,46 @@ bool pkgAcquire::Worker::RunMessages() |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
PrepareFiles("400::URIFailure", Itm); |
|
|
|
|
|
|
|
// Display update before completion
|
|
|
|
if (Log != 0 && Log->MorePulses == true) |
|
|
|
Log->Pulse(Itm->Owner->GetOwner()); |
|
|
|
|
|
|
|
pkgAcquire::Item *Owner = Itm->Owner; |
|
|
|
pkgAcquire::ItemDesc Desc = *Itm; |
|
|
|
|
|
|
|
if (RealFileExists(Owner->DestFile)) |
|
|
|
ChangeOwnerAndPermissionOfFile("400::URIFailure", Owner->DestFile.c_str(), "root", "root", 0644); |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
Log->Pulse((*O)->GetOwner()); |
|
|
|
|
|
|
|
std::vector<Item*> const ItmOwners = Itm->Owners; |
|
|
|
OwnerQ->ItemDone(Itm); |
|
|
|
Itm = NULL; |
|
|
|
|
|
|
|
// set some status
|
|
|
|
if(LookupTag(Message,"FailReason") == "Timeout" || |
|
|
|
LookupTag(Message,"FailReason") == "TmpResolveFailure" || |
|
|
|
LookupTag(Message,"FailReason") == "ResolveFailure" || |
|
|
|
LookupTag(Message,"FailReason") == "ConnectionRefused") |
|
|
|
Owner->Status = pkgAcquire::Item::StatTransientNetworkError; |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) |
|
|
|
{ |
|
|
|
// set some status
|
|
|
|
if(LookupTag(Message,"FailReason") == "Timeout" || |
|
|
|
LookupTag(Message,"FailReason") == "TmpResolveFailure" || |
|
|
|
LookupTag(Message,"FailReason") == "ResolveFailure" || |
|
|
|
LookupTag(Message,"FailReason") == "ConnectionRefused") |
|
|
|
(*O)->Status = pkgAcquire::Item::StatTransientNetworkError; |
|
|
|
|
|
|
|
Owner->Failed(Message,Config); |
|
|
|
ItemDone(); |
|
|
|
(*O)->Failed(Message,Config); |
|
|
|
|
|
|
|
if (Log != 0) |
|
|
|
Log->Fail(Desc); |
|
|
|
if (Log != 0) |
|
|
|
Log->Fail((*O)->GetItemDesc()); |
|
|
|
} |
|
|
|
ItemDone(); |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 401 General Failure
|
|
|
|
case 401: |
|
|
|
_error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str()); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// 403 Media Change
|
|
|
|
case 403: |
|
|
|
MediaChange(Message); |
|
|
|
MediaChange(Message); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
@ -432,7 +497,7 @@ bool pkgAcquire::Worker::Capabilities(string Message) |
|
|
|
{ |
|
|
|
if (Config == 0) |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
Config->Version = LookupTag(Message,"Version"); |
|
|
|
Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false); |
|
|
|
Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false); |
|
|
@ -447,13 +512,13 @@ bool pkgAcquire::Worker::Capabilities(string Message) |
|
|
|
clog << "Configured access method " << Config->Access << endl; |
|
|
|
clog << "Version:" << Config->Version << |
|
|
|
" SingleInstance:" << Config->SingleInstance << |
|
|
|
" Pipeline:" << Config->Pipeline << |
|
|
|
" SendConfig:" << Config->SendConfig << |
|
|
|
" LocalOnly: " << Config->LocalOnly << |
|
|
|
" NeedsCleanup: " << Config->NeedsCleanup << |
|
|
|
" Pipeline:" << Config->Pipeline << |
|
|
|
" SendConfig:" << Config->SendConfig << |
|
|
|
" LocalOnly: " << Config->LocalOnly << |
|
|
|
" NeedsCleanup: " << Config->NeedsCleanup << |
|
|
|
" Removable: " << Config->Removable << endl; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
@ -463,14 +528,14 @@ bool pkgAcquire::Worker::Capabilities(string Message) |
|
|
|
bool pkgAcquire::Worker::MediaChange(string Message) |
|
|
|
{ |
|
|
|
int status_fd = _config->FindI("APT::Status-Fd",-1); |
|
|
|
if(status_fd > 0) |
|
|
|
if(status_fd > 0) |
|
|
|
{ |
|
|
|
string Media = LookupTag(Message,"Media"); |
|
|
|
string Drive = LookupTag(Message,"Drive"); |
|
|
|
string Drive = LookupTag(Message,"Drive"); |
|
|
|
ostringstream msg,status; |
|
|
|
ioprintf(msg,_("Please insert the disc labeled: " |
|
|
|
"'%s' " |
|
|
|
"in the drive '%s' and press enter."), |
|
|
|
"in the drive '%s' and press [Enter]."), |
|
|
|
Media.c_str(),Drive.c_str()); |
|
|
|
status << "media-change: " // message
|
|
|
|
<< Media << ":" // media
|
|
|
@ -536,21 +601,29 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) |
|
|
|
{ |
|
|
|
if (OutFd == -1) |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
string Message = "600 URI Acquire\n"; |
|
|
|
Message.reserve(300); |
|
|
|
Message += "URI: " + Item->URI; |
|
|
|
Message += "\nFilename: " + Item->Owner->DestFile; |
|
|
|
HashStringList const hsl = Item->Owner->HashSums(); |
|
|
|
|
|
|
|
HashStringList const hsl = Item->GetExpectedHashes(); |
|
|
|
for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) |
|
|
|
Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); |
|
|
|
if(Item->Owner->FileSize > 0) |
|
|
|
|
|
|
|
if (hsl.FileSize() == 0) |
|
|
|
{ |
|
|
|
string MaximumSize; |
|
|
|
strprintf(MaximumSize, "%llu", Item->Owner->FileSize); |
|
|
|
Message += "\nMaximum-Size: " + MaximumSize; |
|
|
|
unsigned long long FileSize = Item->GetMaximumSize(); |
|
|
|
if(FileSize > 0) |
|
|
|
{ |
|
|
|
string MaximumSize; |
|
|
|
strprintf(MaximumSize, "%llu", FileSize); |
|
|
|
Message += "\nMaximum-Size: " + MaximumSize; |
|
|
|
} |
|
|
|
} |
|
|
|
Message += Item->Owner->Custom600Headers(); |
|
|
|
|
|
|
|
Item->SyncDestinationFiles(); |
|
|
|
Message += Item->Custom600Headers(); |
|
|
|
Message += "\n\n"; |
|
|
|
|
|
|
|
if (RealFileExists(Item->Owner->DestFile)) |
|
|
@ -564,7 +637,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) |
|
|
|
clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl; |
|
|
|
OutQueue += Message; |
|
|
|
OutReady = true; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
@ -586,7 +659,7 @@ bool pkgAcquire::Worker::OutFdReady() |
|
|
|
OutQueue.erase(0,Res); |
|
|
|
if (OutQueue.empty() == true) |
|
|
|
OutReady = false; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
@ -608,7 +681,7 @@ bool pkgAcquire::Worker::InFdReady() |
|
|
|
bool pkgAcquire::Worker::MethodFailure() |
|
|
|
{ |
|
|
|
_error->Error("Method %s has died unexpectedly!",Access.c_str()); |
|
|
|
|
|
|
|
|
|
|
|
// do not reap the child here to show meaningfull error to the user
|
|
|
|
ExecWait(Process,Access.c_str(),false); |
|
|
|
Process = -1; |
|
|
@ -620,26 +693,22 @@ bool pkgAcquire::Worker::MethodFailure() |
|
|
|
InReady = false; |
|
|
|
OutQueue = string(); |
|
|
|
MessageQueue.erase(MessageQueue.begin(),MessageQueue.end()); |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
// Worker::Pulse - Called periodically /*{{{*/
|
|
|
|
// 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 /*{{{*/
|
|
|
@ -653,3 +722,33 @@ void pkgAcquire::Worker::ItemDone() |
|
|
|
Status = string(); |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm)/*{{{*/ |
|
|
|
{ |
|
|
|
if (RealFileExists(Itm->Owner->DestFile)) |
|
|
|
{ |
|
|
|
ChangeOwnerAndPermissionOfFile(caller, Itm->Owner->DestFile.c_str(), "root", "root", 0644); |
|
|
|
std::string const filename = Itm->Owner->DestFile; |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
{ |
|
|
|
pkgAcquire::Item const * const Owner = *O; |
|
|
|
if (Owner->DestFile == filename) |
|
|
|
continue; |
|
|
|
unlink(Owner->DestFile.c_str()); |
|
|
|
if (link(filename.c_str(), Owner->DestFile.c_str()) != 0) |
|
|
|
{ |
|
|
|
// different mounts can't happen for us as we download to lists/ by default,
|
|
|
|
// but if the system is reused by others the locations can potentially be on
|
|
|
|
// different disks, so use symlink as poor-men replacement.
|
|
|
|
// FIXME: Real copying as last fallback, but that is costly, so offload to a method preferable
|
|
|
|
if (symlink(filename.c_str(), Owner->DestFile.c_str()) != 0) |
|
|
|
_error->Error("Can't create (sym)link of file %s to %s", filename.c_str(), Owner->DestFile.c_str()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) |
|
|
|
unlink((*O)->DestFile.c_str()); |
|
|
|
} |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|