diff options
author | Michael Vogt <egon@tas> | 2006-12-07 11:45:13 +0100 |
---|---|---|
committer | Michael Vogt <egon@tas> | 2006-12-07 11:45:13 +0100 |
commit | 207825063be51d68768e242f06b26ee6fccd3aaf (patch) | |
tree | 4c755597279d2574e787460c5d0f3bc34d132a64 /methods | |
parent | 7106240056767caad5a55fe9c542842065cb5829 (diff) | |
parent | 1c05ebd6da9491d316997a98db1451f7b0526603 (diff) |
merged with apt--mvo
Diffstat (limited to 'methods')
-rw-r--r-- | methods/cdrom.cc | 3 | ||||
-rw-r--r-- | methods/connect.cc | 2 | ||||
-rw-r--r-- | methods/ftp.cc | 7 | ||||
-rw-r--r-- | methods/gpgv.cc | 44 | ||||
-rw-r--r-- | methods/gzip.cc | 8 | ||||
-rw-r--r-- | methods/http.cc | 63 | ||||
-rw-r--r-- | methods/http.h | 5 |
7 files changed, 101 insertions, 31 deletions
diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 41eb8a0ee..d6b8eae75 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -166,8 +166,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm) if (MediaFail(Get.Host,CDROM) == false) { CurrentID = "FAIL"; - Fail(_("Wrong CD-ROM"),true); - return true; + return _error->Error(_("Disk not found.")); } } diff --git a/methods/connect.cc b/methods/connect.cc index 4e48927ed..8c2ac6d56 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -103,6 +103,8 @@ static bool DoConnect(struct addrinfo *Addr,string Host, if (Err != 0) { errno = Err; + if(errno == ECONNREFUSED) + Owner->SetFailExtraMsg("\nFailReason: ConnectionRefused"); return _error->Errno("connect",_("Could not connect to %s:%s (%s)."),Host.c_str(), Service,Name); } diff --git a/methods/ftp.cc b/methods/ftp.cc index f595e0ca4..0c2aa00a7 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -1055,9 +1055,12 @@ bool FtpMethod::Fetch(FetchItem *Itm) UBuf.modtime = FailTime; utime(FailFile.c_str(),&UBuf); - // If the file is missing we hard fail otherwise transient fail - if (Missing == true) + // If the file is missing we hard fail and delete the destfile + // otherwise transient fail + if (Missing == true) { + unlink(FailFile.c_str()); return false; + } Fail(true); return true; } diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 5cb154f66..227e08d63 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -11,16 +11,18 @@ #include <errno.h> #include <sys/wait.h> #include <iostream> +#include <sstream> #define GNUPGPREFIX "[GNUPG:]" #define GNUPGBADSIG "[GNUPG:] BADSIG" #define GNUPGNOPUBKEY "[GNUPG:] NO_PUBKEY" #define GNUPGVALIDSIG "[GNUPG:] VALIDSIG" +#define GNUPGNODATA "[GNUPG:] NODATA" class GPGVMethod : public pkgAcqMethod { private: - const char *VerifyGetSigners(const char *file, const char *outfile, + string VerifyGetSigners(const char *file, const char *outfile, vector<string> &GoodSigners, vector<string> &BadSigners, vector<string> &NoPubKeySigners); @@ -32,11 +34,15 @@ class GPGVMethod : public pkgAcqMethod GPGVMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {}; }; -const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, +string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, vector<string> &GoodSigners, vector<string> &BadSigners, vector<string> &NoPubKeySigners) { + // setup a (empty) stringstream for formating the return value + std::stringstream ret; + ret.str(""); + if (_config->FindB("Debug::Acquire::gpgv", false)) { std::cerr << "inside VerifyGetSigners" << std::endl; @@ -54,9 +60,11 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::cerr << "Keyring path: " << pubringpath << std::endl; } - if (stat(pubringpath.c_str(), &buff) != 0) - return (string("Couldn't access keyring: ") + strerror(errno)).c_str(); - + if (stat(pubringpath.c_str(), &buff) != 0) + { + ioprintf(ret, _("Couldn't access keyring: '%s'"), strerror(errno)); + return ret.str(); + } if (pipe(fd) < 0) { return "Couldn't create pipe"; @@ -65,7 +73,7 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, pid = fork(); if (pid < 0) { - return (string("Couldn't spawn new process") + strerror(errno)).c_str(); + return string("Couldn't spawn new process") + strerror(errno); } else if (pid == 0) { @@ -164,7 +172,12 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::cerr << "Got NO_PUBKEY " << std::endl; NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - + if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got NODATA! " << std::endl; + BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0) { char *sig = buffer + sizeof(GNUPGPREFIX); @@ -189,7 +202,7 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, { if (GoodSigners.empty()) return _("Internal error: Good signature, but could not determine key fingerprint?!"); - return NULL; + return ""; } else if (WEXITSTATUS(status) == 1) { @@ -197,9 +210,8 @@ const char *GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, } else if (WEXITSTATUS(status) == 111) { - // FIXME String concatenation considered harmful. - return (string(_("Could not execute ")) + gpgvpath + - string(_(" to verify signature (is gnupg installed?)"))).c_str(); + ioprintf(ret, _("Could not execute '%s' to verify signature (is gnupg installed?)"), gpgvpath.c_str()); + return ret.str(); } else { @@ -221,8 +233,8 @@ bool GPGVMethod::Fetch(FetchItem *Itm) URIStart(Res); // Run gpgv on file, extract contents and get the key ID of the signer - const char *msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), - GoodSigners, BadSigners, NoPubKeySigners); + string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), + GoodSigners, BadSigners, NoPubKeySigners); if (GoodSigners.empty() || !BadSigners.empty() || !NoPubKeySigners.empty()) { string errmsg; @@ -247,7 +259,11 @@ bool GPGVMethod::Fetch(FetchItem *Itm) errmsg += (*I + "\n"); } } - return _error->Error(errmsg.c_str()); + // this is only fatal if we have no good sigs or if we have at + // least one bad signature. good signatures and NoPubKey signatures + // happen easily when a file is signed with multiple signatures + if(GoodSigners.empty() or !BadSigners.empty()) + return _error->Error(errmsg.c_str()); } // Transfer the modification times diff --git a/methods/gzip.cc b/methods/gzip.cc index 809afc0fc..f732c0b86 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -52,6 +52,13 @@ bool GzipMethod::Fetch(FetchItem *Itm) // Open the source and destination files FileFd From(Path,FileFd::ReadOnly); + // if the file is empty, just rename it and return + if(From.Size() == 0) + { + rename(Path.c_str(), Itm->DestFile.c_str()); + return true; + } + int GzOut[2]; if (pipe(GzOut) < 0) return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog); @@ -111,6 +118,7 @@ bool GzipMethod::Fetch(FetchItem *Itm) if (To.Write(Buffer,Count) == false) { Failed = true; + FromGz.Close(); break; } } diff --git a/methods/http.cc b/methods/http.cc index e2337a9ba..c6623c46f 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -59,6 +59,11 @@ unsigned long TimeOut = 120; bool Debug = false; +unsigned long CircleBuf::BwReadLimit=0; +unsigned long CircleBuf::BwTickReadData=0; +struct timeval CircleBuf::BwReadTick={0,0}; +const unsigned int CircleBuf::BW_HZ=10; + // CircleBuf::CircleBuf - Circular input buffer /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -66,6 +71,8 @@ CircleBuf::CircleBuf(unsigned long Size) : Size(Size), Hash(0) { Buf = new unsigned char[Size]; Reset(); + + CircleBuf::BwReadLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024; } /*}}}*/ // CircleBuf::Reset - Reset to the default state /*{{{*/ @@ -91,16 +98,45 @@ void CircleBuf::Reset() is non-blocking.. */ bool CircleBuf::Read(int Fd) { + unsigned long BwReadMax; + while (1) { // Woops, buffer is full if (InP - OutP == Size) return true; + // what's left to read in this tick + BwReadMax = CircleBuf::BwReadLimit/BW_HZ; + + if(CircleBuf::BwReadLimit) { + struct timeval now; + gettimeofday(&now,0); + + unsigned long d = (now.tv_sec-CircleBuf::BwReadTick.tv_sec)*1000000 + + now.tv_usec-CircleBuf::BwReadTick.tv_usec; + if(d > 1000000/BW_HZ) { + CircleBuf::BwReadTick = now; + CircleBuf::BwTickReadData = 0; + } + + if(CircleBuf::BwTickReadData >= BwReadMax) { + usleep(1000000/BW_HZ); + return true; + } + } + // Write the buffer segment int Res; - Res = read(Fd,Buf + (InP%Size),LeftRead()); + if(CircleBuf::BwReadLimit) { + Res = read(Fd,Buf + (InP%Size), + BwReadMax > LeftRead() ? LeftRead() : BwReadMax); + } else + Res = read(Fd,Buf + (InP%Size),LeftRead()); + if(Res > 0 && BwReadLimit > 0) + CircleBuf::BwTickReadData += Res; + if (Res == 0) return false; if (Res < 0) @@ -205,28 +241,23 @@ bool CircleBuf::WriteTillEl(string &Data,bool Single) if (Buf[I%Size] != '\n') continue; ++I; - if (I < InP && Buf[I%Size] == '\r') - ++I; if (Single == false) { - if (Buf[I%Size] != '\n') - continue; - ++I; if (I < InP && Buf[I%Size] == '\r') ++I; + if (I >= InP || Buf[I%Size] != '\n') + continue; + ++I; } - if (I > InP) - I = InP; - Data = ""; while (OutP < I) { unsigned long Sz = LeftWrite(); if (Sz == 0) return false; - if (I - OutP < LeftWrite()) + if (I - OutP < Sz) Sz = I - OutP; Data += string((char *)(Buf + (OutP%Size)),Sz); OutP += Sz; @@ -626,7 +657,7 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out) will glitch HTTP/1.0 proxies because they do not filter it out and pass it on, HTTP/1.1 says the connection should default to keep alive and we expect the proxy to do this */ - if (Proxy.empty() == true) + if (Proxy.empty() == true || Proxy.Host.empty()) sprintf(Buf,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n", QuoteString(Uri.Path,"~").c_str(),ProperHost.c_str()); else @@ -788,7 +819,10 @@ bool HttpMethod::Flush(ServerState *Srv) { if (File != 0) { - SetNonBlock(File->Fd(),false); + // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking + // can't be set + if (File->Name() != "/dev/null") + SetNonBlock(File->Fd(),false); if (Srv->In.WriteSpace() == false) return true; @@ -816,7 +850,10 @@ bool HttpMethod::ServerDie(ServerState *Srv) // Dump the buffer to the file if (Srv->State == ServerState::Data) { - SetNonBlock(File->Fd(),false); + // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking + // can't be set + if (File->Name() != "/dev/null") + SetNonBlock(File->Fd(),false); while (Srv->In.WriteSpace() == true) { if (Srv->In.Write(File->Fd()) == false) diff --git a/methods/http.h b/methods/http.h index c5a4d0e86..541e2952c 100644 --- a/methods/http.h +++ b/methods/http.h @@ -31,6 +31,11 @@ class CircleBuf unsigned long MaxGet; struct timeval Start; + static unsigned long BwReadLimit; + static unsigned long BwTickReadData; + static struct timeval BwReadTick; + static const unsigned int BW_HZ; + unsigned long LeftRead() { unsigned long Sz = Size - (InP - OutP); |