From 788a8f42c1ec146c812550d076e5fb720e83ae52 Mon Sep 17 00:00:00 2001 From: "Eugene V. Lyubimkin" Date: Mon, 15 Dec 2008 21:17:39 +0200 Subject: Make apt proxy options have the highest priority, unified proxy determining code. --- methods/ftp.cc | 33 +++++++++++++++++++-------------- methods/http.cc | 31 ++++++++++++++++++------------- methods/https.cc | 31 +++++++++++++++++++------------ 3 files changed, 56 insertions(+), 39 deletions(-) (limited to 'methods') diff --git a/methods/ftp.cc b/methods/ftp.cc index 554a24cf5..c91600ad5 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -112,23 +112,28 @@ bool FTPConn::Open(pkgAcqMethod *Owner) Close(); // Determine the proxy setting - if (getenv("ftp_proxy") == 0) + string SpecificProxy = _config->Find("Acquire::ftp::Proxy::" + ServerName.Host); + if (!SpecificProxy.empty()) { - string DefProxy = _config->Find("Acquire::ftp::Proxy"); - string SpecificProxy = _config->Find("Acquire::ftp::Proxy::" + ServerName.Host); - if (SpecificProxy.empty() == false) - { - if (SpecificProxy == "DIRECT") - Proxy = ""; - else - Proxy = SpecificProxy; - } - else - Proxy = DefProxy; + if (SpecificProxy == "DIRECT") + Proxy = ""; + else + Proxy = SpecificProxy; } else - Proxy = getenv("ftp_proxy"); - + { + string DefProxy = _config->Find("Acquire::ftp::Proxy"); + if (!DefProxy.empty()) + { + Proxy = DefProxy; + } + else + { + char* result = getenv("ftp_proxy"); + Proxy = result ? result : ""; + } + } + // Parse no_proxy, a , separated list of domains if (getenv("no_proxy") != 0) { diff --git a/methods/http.cc b/methods/http.cc index b3c791fa0..5d18b3adc 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -309,22 +309,27 @@ bool ServerState::Open() Persistent = true; // Determine the proxy setting - if (getenv("http_proxy") == 0) + string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); + if (!SpecificProxy.empty()) { - string DefProxy = _config->Find("Acquire::http::Proxy"); - string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); - if (SpecificProxy.empty() == false) - { - if (SpecificProxy == "DIRECT") - Proxy = ""; - else - Proxy = SpecificProxy; - } - else - Proxy = DefProxy; + if (SpecificProxy == "DIRECT") + Proxy = ""; + else + Proxy = SpecificProxy; } else - Proxy = getenv("http_proxy"); + { + string DefProxy = _config->Find("Acquire::http::Proxy"); + if (!DefProxy.empty()) + { + Proxy = DefProxy; + } + else + { + char* result = getenv("http_proxy"); + Proxy = result ? result : ""; + } + } // Parse no_proxy, a , separated list of domains if (getenv("no_proxy") != 0) diff --git a/methods/https.cc b/methods/https.cc index 98dfeefa1..728869fa2 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -61,19 +61,26 @@ void HttpsMethod::SetupProxy() URI ServerName = Queue->Uri; // Determine the proxy setting - if (getenv("http_proxy") == 0) + string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); + if (!SpecificProxy.empty()) { - string DefProxy = _config->Find("Acquire::http::Proxy"); - string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); - if (SpecificProxy.empty() == false) - { - if (SpecificProxy == "DIRECT") - Proxy = ""; - else - Proxy = SpecificProxy; - } - else - Proxy = DefProxy; + if (SpecificProxy == "DIRECT") + Proxy = ""; + else + Proxy = SpecificProxy; + } + else + { + string DefProxy = _config->Find("Acquire::http::Proxy"); + if (!DefProxy.empty()) + { + Proxy = DefProxy; + } + else + { + char* result = getenv("http_proxy"); + Proxy = result ? result : ""; + } } // Parse no_proxy, a , separated list of domains -- cgit v1.2.3 From a06f61bbb328ee218afbd367248f6f2338186e19 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 8 Apr 2009 22:49:23 +0200 Subject: * methods/gpgv.cc: - properly check for expired and revoked keys (closes: #433091) --- methods/gpgv.cc | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'methods') diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 9f4683e6e..470b47fd4 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -17,13 +17,18 @@ #define GNUPGBADSIG "[GNUPG:] BADSIG" #define GNUPGNOPUBKEY "[GNUPG:] NO_PUBKEY" #define GNUPGVALIDSIG "[GNUPG:] VALIDSIG" +#define GNUPGGOODSIG "[GNUPG:] GOODSIG" +#define GNUPGKEYEXPIRED "[GNUPG:] KEYEXPIRED" +#define GNUPGREVKEYSIG "[GNUPG:] REVKEYSIG" #define GNUPGNODATA "[GNUPG:] NODATA" class GPGVMethod : public pkgAcqMethod { private: string VerifyGetSigners(const char *file, const char *outfile, - vector &GoodSigners, vector &BadSigners, + vector &GoodSigners, + vector &BadSigners, + vector &WorthlessSigners, vector &NoPubKeySigners); protected: @@ -37,6 +42,7 @@ class GPGVMethod : public pkgAcqMethod string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, vector &GoodSigners, vector &BadSigners, + vector &WorthlessSigners, vector &NoPubKeySigners) { // setup a (empty) stringstream for formating the return value @@ -179,15 +185,27 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::cerr << "Got NODATA! " << std::endl; BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0) + if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got KEYEXPIRED! " << std::endl; + WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } + if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0) + { + if (_config->FindB("Debug::Acquire::gpgv", false)) + std::cerr << "Got REVKEYSIG! " << std::endl; + WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); + } + if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0) { char *sig = buffer + sizeof(GNUPGPREFIX); - char *p = sig + sizeof("VALIDSIG"); + char *p = sig + sizeof("GOODSIG"); while (*p && isxdigit(*p)) p++; *p = 0; if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got VALIDSIG, key ID:" << sig << std::endl; + std::cerr << "Got GOODSIG, key ID:" << sig << std::endl; GoodSigners.push_back(string(sig)); } } @@ -227,6 +245,8 @@ bool GPGVMethod::Fetch(FetchItem *Itm) string keyID; vector GoodSigners; vector BadSigners; + // a worthless signature is a expired or revoked one + vector WorthlessSigners; vector NoPubKeySigners; FetchResult Res; @@ -235,13 +255,14 @@ bool GPGVMethod::Fetch(FetchItem *Itm) // Run gpgv on file, extract contents and get the key ID of the signer string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), - GoodSigners, BadSigners, NoPubKeySigners); + GoodSigners, BadSigners, WorthlessSigners, + NoPubKeySigners); if (GoodSigners.empty() || !BadSigners.empty() || !NoPubKeySigners.empty()) { string errmsg; // In this case, something bad probably happened, so we just go // with what the other method gave us for an error message. - if (BadSigners.empty() && NoPubKeySigners.empty()) + if (BadSigners.empty() && WorthlessSigners.empty() && NoPubKeySigners.empty()) errmsg = msg; else { @@ -252,6 +273,13 @@ bool GPGVMethod::Fetch(FetchItem *Itm) I != BadSigners.end(); I++) errmsg += (*I + "\n"); } + if (!WorthlessSigners.empty()) + { + errmsg += _("The following signatures were invalid:\n"); + for (vector::iterator I = WorthlessSigners.begin(); + I != WorthlessSigners.end(); I++) + errmsg += (*I + "\n"); + } if (!NoPubKeySigners.empty()) { errmsg += _("The following signatures couldn't be verified because the public key is not available:\n"); -- cgit v1.2.3 From 09fab2442c2ab9a503841d3dcd56b3c0c3efb502 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 9 Apr 2009 04:36:34 +0200 Subject: * apt-pkg/contrib/strutl.cc: - fix TimeToStr i18n (LP: #289807) * [ABI break] merge support for http redirects, thanks to Jeff Licquia and Anthony Towns * [ABI break] use int for the package IDs (thanks to Steve Cotton) * apt-pkg/pkgcache.cc: - do not run "dpkg --configure pkg" if pkg is in trigger-awaited state (LP: #322955) * methods/https.cc: - add Acquire::https::AllowRedirect support * Clarify the --help for 'purge' (LP: #243948) * cmdline/apt-get.cc - fix "apt-get source pkg" if there is a binary package and a source package of the same name but from different packages (LP: #330103) * cmdline/acqprogress.cc: - Call pkgAcquireStatus::Pulse even if quiet, so that we still get dlstatus messages on the status-fd (LP: #290234). --- methods/http.cc | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- methods/http.h | 3 +++ methods/https.cc | 6 ++++- methods/makefile | 2 +- 4 files changed, 86 insertions(+), 3 deletions(-) (limited to 'methods') diff --git a/methods/http.cc b/methods/http.cc index b3c791fa0..1bf798da4 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include // Internet stuff @@ -57,6 +58,7 @@ int HttpMethod::FailFd = -1; time_t HttpMethod::FailTime = 0; unsigned long PipelineDepth = 10; unsigned long TimeOut = 120; +bool AllowRedirect = false; bool Debug = false; URI Proxy; @@ -628,6 +630,12 @@ bool ServerState::HeaderLine(string Line) return true; } + if (stringcasecmp(Tag,"Location:") == 0) + { + Location = Val; + return true; + } + return true; } /*}}}*/ @@ -900,7 +908,9 @@ bool HttpMethod::ServerDie(ServerState *Srv) 1 - IMS hit 3 - Unrecoverable error 4 - Error with error content page - 5 - Unrecoverable non-server error (close the connection) */ + 5 - Unrecoverable non-server error (close the connection) + 6 - Try again with a new or changed URI + */ int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) { // Not Modified @@ -912,6 +922,27 @@ int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) return 1; } + /* Redirect + * + * Note that it is only OK for us to treat all redirection the same + * because we *always* use GET, not other HTTP methods. There are + * three redirection codes for which it is not appropriate that we + * redirect. Pass on those codes so the error handling kicks in. + */ + if (AllowRedirect + && (Srv->Result > 300 && Srv->Result < 400) + && (Srv->Result != 300 // Multiple Choices + && Srv->Result != 304 // Not Modified + && Srv->Result != 306)) // (Not part of HTTP/1.1, reserved) + { + if (!Srv->Location.empty()) + { + NextURI = Srv->Location; + return 6; + } + /* else pass through for error message */ + } + /* We have a reply we dont handle. This should indicate a perm server failure */ if (Srv->Result < 200 || Srv->Result >= 300) @@ -1026,6 +1057,7 @@ bool HttpMethod::Configuration(string Message) if (pkgAcqMethod::Configuration(Message) == false) return false; + AllowRedirect = _config->FindB("Acquire::http::AllowRedirect",true); TimeOut = _config->FindI("Acquire::http::Timeout",TimeOut); PipelineDepth = _config->FindI("Acquire::http::Pipeline-Depth", PipelineDepth); @@ -1039,6 +1071,10 @@ bool HttpMethod::Configuration(string Message) /* */ int HttpMethod::Loop() { + typedef vector StringVector; + typedef vector::iterator StringVectorIterator; + map Redirected; + signal(SIGTERM,SigTerm); signal(SIGINT,SigTerm); @@ -1225,6 +1261,46 @@ int HttpMethod::Loop() break; } + // Try again with a new URL + case 6: + { + // Clear rest of response if there is content + if (Server->HaveContent) + { + File = new FileFd("/dev/null",FileFd::WriteExists); + Server->RunData(); + delete File; + File = 0; + } + + /* Detect redirect loops. No more redirects are allowed + after the same URI is seen twice in a queue item. */ + StringVector &R = Redirected[Queue->DestFile]; + bool StopRedirects = false; + if (R.size() == 0) + R.push_back(Queue->Uri); + else if (R[0] == "STOP" || R.size() > 10) + StopRedirects = true; + else + { + for (StringVectorIterator I = R.begin(); I != R.end(); I++) + if (Queue->Uri == *I) + { + R[0] = "STOP"; + break; + } + + R.push_back(Queue->Uri); + } + + if (StopRedirects == false) + Redirect(NextURI); + else + Fail(); + + break; + } + default: Fail(_("Internal error")); break; diff --git a/methods/http.h b/methods/http.h index 6753a9901..13f02ec77 100644 --- a/methods/http.h +++ b/methods/http.h @@ -99,6 +99,7 @@ struct ServerState enum {Chunked,Stream,Closes} Encoding; enum {Header, Data} State; bool Persistent; + string Location; // This is a Persistent attribute of the server itself. bool Pipeline; @@ -143,6 +144,8 @@ class HttpMethod : public pkgAcqMethod static time_t FailTime; static void SigTerm(int); + string NextURI; + public: friend class ServerState; diff --git a/methods/https.cc b/methods/https.cc index 98dfeefa1..8bf44b52a 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -208,6 +208,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + // set redirect options and default to 10 redirects + bool AllowRedirect = _config->FindI("Acquire::https::AllowRedirect", true); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, AllowRedirect); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10); + // debug if(_config->FindB("Debug::Acquire::https", false)) curl_easy_setopt(curl, CURLOPT_VERBOSE, true); @@ -248,7 +253,6 @@ bool HttpsMethod::Fetch(FetchItem *Itm) // cleanup if(success != 0) { - unlink(File->Name().c_str()); _error->Error("%s", curl_errorstr); Fail(); return true; diff --git a/methods/makefile b/methods/makefile index d9481dbcc..78bdbc96f 100644 --- a/methods/makefile +++ b/methods/makefile @@ -7,7 +7,7 @@ include ../buildlib/defaults.mak BIN := $(BIN)/methods # FIXME.. -LIB_APT_PKG_MAJOR = 4.6 +LIB_APT_PKG_MAJOR = 4.7 APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR) # The file method -- cgit v1.2.3 From 81e9789b12374073e848c73c79e235f82c14df44 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 9 Jun 2009 17:33:22 +0200 Subject: [ABI break] support '#' in apt.conf and /etc/apt/preferences (closes: #189866) --- methods/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/makefile b/methods/makefile index 78bdbc96f..589f9fa1c 100644 --- a/methods/makefile +++ b/methods/makefile @@ -7,7 +7,7 @@ include ../buildlib/defaults.mak BIN := $(BIN)/methods # FIXME.. -LIB_APT_PKG_MAJOR = 4.7 +LIB_APT_PKG_MAJOR = 4.8 APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR) # The file method -- cgit v1.2.3 From dda7233c5d3879f2580543ead0ad7cd76196a160 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 18 Aug 2009 20:15:13 +0200 Subject: Allow empty Reason-Phase in the Status-Lines, which is allowed by rtf http://www.w3.org/Protocols/rfc2616/rfc2616.html . Fixed by removing a space which will now be visibly in the errormessages, but as this errors should never happen anyway and an extra space doesn't harm we don't removed it. * methods/http.cc: - allow empty Reason-Phase in Status-Line to please squid, thanks Modestas Vainius for noticing! (Closes: #531157, LP: #411435) --- methods/http.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'methods') diff --git a/methods/http.cc b/methods/http.cc index 006e89394..df62034e3 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -547,7 +547,7 @@ bool ServerState::HeaderLine(string Line) // Evil servers return no version if (Line[4] == '/') { - if (sscanf(Line.c_str(),"HTTP/%u.%u %u %[^\n]",&Major,&Minor, + if (sscanf(Line.c_str(),"HTTP/%u.%u %u%[^\n]",&Major,&Minor, &Result,Code) != 4) return _error->Error(_("The HTTP server sent an invalid reply header")); } @@ -555,7 +555,7 @@ bool ServerState::HeaderLine(string Line) { Major = 0; Minor = 9; - if (sscanf(Line.c_str(),"HTTP %u %[^\n]",&Result,Code) != 2) + if (sscanf(Line.c_str(),"HTTP %u%[^\n]",&Result,Code) != 2) return _error->Error(_("The HTTP server sent an invalid reply header")); } -- cgit v1.2.3 From ebf2e25b204195892b6c4866b1517755efb590b4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 8 Sep 2009 23:11:11 +0200 Subject: add text at the top without failing in rred (Closes: #545694) Patch from Bernhard R. Link, thanks! --- methods/rred.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/rred.cc b/methods/rred.cc index 6fa57f3a6..27d95bdde 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -174,7 +174,7 @@ int RredMethod::ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, hash); /* read the rest from infile */ - if (result > 0) { + if (result >= 0) { while (fgets(buffer, BUF_SIZE, in_file) != NULL) { written = fwrite(buffer, 1, strlen(buffer), out_file); hash->Add((unsigned char*)buffer, written); -- cgit v1.2.3 From cdd5a135d9232123dc3650ed1c1cb31d1e24de0b Mon Sep 17 00:00:00 2001 From: "bubulle@debian.org" <> Date: Sat, 26 Sep 2009 19:45:15 +0200 Subject: Fix some typos from #479997 --- methods/connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/connect.cc b/methods/connect.cc index 355bd5c4d..b5f48907e 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -237,6 +237,6 @@ bool Connect(string Host,int Port,const char *Service,int DefPort,int &Fd, if (_error->PendingError() == true) return false; - return _error->Error(_("Unable to connect to %s %s:"),Host.c_str(),ServStr); + return _error->Error(_("Unable to connect to %s:%s:"),Host.c_str(),ServStr); } /*}}}*/ -- cgit v1.2.3 From f465a80f6e0e0cc3edae1870881135ced824c9e3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 12 Oct 2009 16:24:34 +0200 Subject: methods/https.cc: Add support for authentication using netrc (Closes: #518473), patch by Jussi Hakala . --- methods/https.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index 37d93e308..79e6fea3f 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -135,6 +135,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false); curl_easy_setopt(curl, CURLOPT_FAILONERROR, true); curl_easy_setopt(curl, CURLOPT_FILETIME, true); + curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); // SSL parameters are set by default to the common (non mirror-specific) value // if available (or a default one) and gets overload by mirror-specific ones. -- cgit v1.2.3 From 592b78001c381f9cca6f20d8d1d47696bb98c0d1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 16 Oct 2009 15:36:28 +0200 Subject: port netrc support from maemon --- methods/http.cc | 7 +++++-- methods/https.cc | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'methods') diff --git a/methods/http.cc b/methods/http.cc index 1eba0f279..6bfe80baf 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include + // Internet stuff #include @@ -49,7 +51,6 @@ #include "connect.h" #include "rfc2553emu.h" #include "http.h" - /*}}}*/ using namespace std; @@ -725,9 +726,11 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out) Base64Encode(Proxy.User + ":" + Proxy.Password) + "\r\n"; if (Uri.User.empty() == false || Uri.Password.empty() == false) + { + maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc")); Req += string("Authorization: Basic ") + Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n"; - + } Req += "User-Agent: Debian APT-HTTP/1.3 ("VERSION")\r\n\r\n"; if (Debug == true) diff --git a/methods/https.cc b/methods/https.cc index 37d93e308..a86c78029 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -126,6 +127,8 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_reset(curl); SetupProxy(); + maybe_add_auth (Uri, _config->FindFile("Dir::ETc::netrc")); + // callbacks curl_easy_setopt(curl, CURLOPT_URL, Itm->Uri.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); -- cgit v1.2.3 From 1de1f70383ea2d44147ccaceff280fd70faf4c81 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 16 Oct 2009 15:42:05 +0200 Subject: add maybe_add_auth for ftp as well --- methods/ftp.cc | 4 +++- methods/http.cc | 2 +- methods/https.cc | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'methods') diff --git a/methods/ftp.cc b/methods/ftp.cc index c91600ad5..eb398666f 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -982,7 +982,9 @@ bool FtpMethod::Fetch(FetchItem *Itm) FetchResult Res; Res.Filename = Itm->DestFile; Res.IMSHit = false; - + + maybe_add_auth (Get, _config->FindFile("Dir::Etc::netrc")); + // Connect to the server if (Server == 0 || Server->Comp(Get) == false) { diff --git a/methods/http.cc b/methods/http.cc index 6bfe80baf..50478b44c 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -725,9 +725,9 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out) Req += string("Proxy-Authorization: Basic ") + Base64Encode(Proxy.User + ":" + Proxy.Password) + "\r\n"; + maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc")); if (Uri.User.empty() == false || Uri.Password.empty() == false) { - maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc")); Req += string("Authorization: Basic ") + Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n"; } diff --git a/methods/https.cc b/methods/https.cc index a86c78029..075d655b7 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -127,7 +127,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_reset(curl); SetupProxy(); - maybe_add_auth (Uri, _config->FindFile("Dir::ETc::netrc")); + maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc")); // callbacks curl_easy_setopt(curl, CURLOPT_URL, Itm->Uri.c_str()); -- cgit v1.2.3 From f1c081b6ad0c5925e9668fd159f1ac6d8ab672bc Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 16 Oct 2009 16:04:41 +0200 Subject: add ftp support, basic debugging --- methods/ftp.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'methods') diff --git a/methods/ftp.cc b/methods/ftp.cc index eb398666f..3e1725823 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From ce26dee77d08876b2022ce480c8f7dd616f94df1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 20 Oct 2009 23:32:27 +0200 Subject: * methods/connect.cc: - display also strerror of "wicked" getaddrinfo errors --- methods/connect.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'methods') diff --git a/methods/connect.cc b/methods/connect.cc index b5f48907e..74e670ebd 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -190,8 +190,8 @@ bool Connect(string Host,int Port,const char *Service,int DefPort,int &Fd, return _error->Error(_("Temporary failure resolving '%s'"), Host.c_str()); } - return _error->Error(_("Something wicked happened resolving '%s:%s' (%i)"), - Host.c_str(),ServStr,Res); + return _error->Error(_("Something wicked happened resolving '%s:%s' (%i - %s)"), + Host.c_str(),ServStr,Res,gai_strerror(Res)); } break; } -- cgit v1.2.3 From 10c9f030e02ccec5c002abc42776f994c124c574 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 24 Oct 2009 17:38:06 +0200 Subject: Bumped libapt version and excluded eglibc from SONAME. (Closes: #448249) Backported from lp:~mvo/apt/debian-experimental Based on patch by Eugene V. Lyubimkin --- methods/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/makefile b/methods/makefile index 134166ba3..f5d80d839 100644 --- a/methods/makefile +++ b/methods/makefile @@ -7,7 +7,7 @@ include ../buildlib/defaults.mak BIN := $(BIN)/methods # FIXME.. -LIB_APT_PKG_MAJOR = 4.8 +LIB_APT_PKG_MAJOR = 4.9 APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR) # The file method -- cgit v1.2.3 From 23d8465817e7bc0d188f36fc2ad14f41ff01c221 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 28 Oct 2009 19:13:56 +0100 Subject: refactor the buildsystem to extract library versions from one file, so it is not needed to change x-files to just increase a version number (because this is far to easy to forget one of the files, which will not result in failures or is bad in general, but is inconsitent.) --- methods/makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'methods') diff --git a/methods/makefile b/methods/makefile index f5d80d839..7bcae6b9b 100644 --- a/methods/makefile +++ b/methods/makefile @@ -6,9 +6,8 @@ SUBDIR=methods include ../buildlib/defaults.mak BIN := $(BIN)/methods -# FIXME.. -LIB_APT_PKG_MAJOR = 4.9 -APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR) +include ../buildlib/libversion.mak +APT_DOMAIN := libapt-pkg$(LIBAPTPKG_MAJOR) # The file method PROGRAM=file -- cgit v1.2.3 From 43cf55db7c2ce7015d365556ed9ab0b8b2cec3ca Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 17 Nov 2009 09:51:31 -0600 Subject: * methods/https.cc: - fix incorrect use of CURLOPT_TIMEOUT, closes: #497983, LP: #354972 thanks to Brian Thomason for the patch --- methods/https.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index 37d93e308..3cbb0088a 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -212,8 +212,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm) // set timeout int timeout = _config->FindI("Acquire::http::Timeout",120); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + //set really low lowspeed timeout (see #497983) + int dlMin = 1; + curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, dlMin); + curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout); // set redirect options and default to 10 redirects bool AllowRedirect = _config->FindI("Acquire::https::AllowRedirect", true); -- cgit v1.2.3 From 5085e660679cdbb51783702898c42000d5db4fba Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 17 Nov 2009 09:55:22 -0600 Subject: methods/https.cc: cleanup for CURLOPT_LOW_SPEED_TIME --- methods/https.cc | 3 +-- methods/https.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index 3cbb0088a..dbc1cf52c 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -214,8 +214,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm) int timeout = _config->FindI("Acquire::http::Timeout",120); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); //set really low lowspeed timeout (see #497983) - int dlMin = 1; - curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, dlMin); + curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout); // set redirect options and default to 10 redirects diff --git a/methods/https.h b/methods/https.h index 2c33d95ee..3f0c416b6 100644 --- a/methods/https.h +++ b/methods/https.h @@ -24,6 +24,8 @@ class HttpsMethod; class HttpsMethod : public pkgAcqMethod { + // minimum speed in bytes/se that triggers download timeout handling + static const int DL_MIN_SPEED = 10; virtual bool Fetch(FetchItem *); static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp); -- cgit v1.2.3 From 01fc89305c7b5fc52d719c6898a9fdf03abf3ce6 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 4 Dec 2009 10:22:56 +0100 Subject: * apt-pkg/contrib/netrc.cc: - check for hostname and then host+path - better debug output * methods/https.cc: - fix bug in netrc integration --- methods/https.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index 075d655b7..585e13848 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -130,7 +130,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm) maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc")); // callbacks - curl_easy_setopt(curl, CURLOPT_URL, Itm->Uri.c_str()); + curl_easy_setopt(curl, CURLOPT_URL, static_cast(Uri).c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback); -- cgit v1.2.3 From bb1293d975294884a95b9cb298432c9cf9ecc995 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 11 Dec 2009 00:23:18 +0100 Subject: Backport rred patches from my own sid branch to the 0.7.25 branch * rewrite and refactor rred method to be able to handle even big (>30 MB) patches (Closes: #554349) and hardening the method itself by using more constants and a return value which can't be misinterpreted as linenumber * Finally adope the patch from Morten Hustveit to be able to optional use mmaps and iovec to increase patch speed - but as this increase memory usage we can always fall back to the "old" method which doesn't depend on mmaps. --- methods/rred.cc | 648 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 464 insertions(+), 184 deletions(-) (limited to 'methods') diff --git a/methods/rred.cc b/methods/rred.cc index 27d95bdde..262c78cab 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -1,202 +1,443 @@ +// Includes /*{{{*/ #include +#include #include #include #include #include #include +#include #include #include #include #include #include - -/* this method implements a patch functionality similar to "patch --ed" that is - * used by the "tiffany" incremental packages download stuff. it differs from - * "ed" insofar that it is way more restricted (and therefore secure). in the - * moment only the "c", "a" and "d" commands of ed are implemented (diff - * doesn't output any other). additionally the records must be reverse sorted - * by line number and may not overlap (diff *seems* to produce this kind of - * output). + /*}}}*/ +/** \brief RredMethod - ed-style incremential patch method {{{ + * + * This method implements a patch functionality similar to "patch --ed" that is + * used by the "tiffany" incremental packages download stuff. It differs from + * "ed" insofar that it is way more restricted (and therefore secure). + * The currently supported ed commands are "change", "add" and + * "delete" (diff doesn't output any other). + * Additionally the records must be reverse sorted by line number and + * may not overlap (diff *seems* to produce this kind of output). * */ +class RredMethod : public pkgAcqMethod { + bool Debug; + // the size of this doesn't really matter (except for performance) + const static int BUF_SIZE = 1024; + // the supported ed commands + enum Mode {MODE_CHANGED='c', MODE_DELETED='d', MODE_ADDED='a'}; + // return values + enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED}; -const char *Prog; + State applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file, + unsigned long &line, char *buffer, Hashes *hash) const; + void ignoreLineInFile(FILE *fin, char *buffer) const; + void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines, + Hashes *hash, char *buffer) const; -class RredMethod : public pkgAcqMethod -{ - bool Debug; - // the size of this doesn't really matter (except for performance) - const static int BUF_SIZE = 1024; - // the ed commands - enum Mode {MODE_CHANGED, MODE_DELETED, MODE_ADDED}; - // return values - enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE}; - // this applies a single hunk, it uses a tail recursion to - // reverse the hunks in the file - int ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line, - char *buffer, unsigned int bufsize, Hashes *hash); - // apply a patch file - int ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, Hashes *hash); - // the methods main method - virtual bool Fetch(FetchItem *Itm); - - public: - - RredMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {}; + State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const; + State patchMMap(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const; + +protected: + // the methods main method + virtual bool Fetch(FetchItem *Itm); + +public: + RredMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {}; }; + /*}}}*/ +/** \brief applyFile - in reverse order with a tail recursion {{{ + * + * As it is expected that the commands are in reversed order in the patch file + * we check in the first half if the command is valid, but doesn't execute it + * and move a step deeper. After reaching the end of the file we apply the + * patches in the correct order: last found command first. + * + * \param ed_cmds patch file to apply + * \param in_file base file we want to patch + * \param out_file file to write the patched result to + * \param line of command operation + * \param buffer internal used read/write buffer + * \param hash the created file for correctness + * \return the success State of the ed command executor + */ +RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file, + unsigned long &line, char *buffer, Hashes *hash) const { + // get the current command and parse it + if (fgets(buffer, BUF_SIZE, ed_cmds) == NULL) { + if (Debug == true) + std::clog << "rred: encounter end of file - we can start patching now." << std::endl; + line = 0; + return ED_OK; + } -int RredMethod::ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line, - char *buffer, unsigned int bufsize, Hashes *hash) { - int pos; - int startline; - int stopline; - int mode; - int written; - char *idx; - - /* get the current command and parse it*/ - if (fgets(buffer, bufsize, ed_cmds) == NULL) { - return line; - } - startline = strtol(buffer, &idx, 10); - if (startline < line) { - return ED_ORDERING; - } - if (*idx == ',') { - idx++; - stopline = strtol(idx, &idx, 10); - } - else { - stopline = startline; - } - if (*idx == 'c') { - mode = MODE_CHANGED; - if (Debug == true) { - std::clog << "changing from line " << startline - << " to " << stopline << std::endl; - } - } - else if (*idx == 'a') { - mode = MODE_ADDED; - if (Debug == true) { - std::clog << "adding after line " << startline << std::endl; - } - } - else if (*idx == 'd') { - mode = MODE_DELETED; - if (Debug == true) { - std::clog << "deleting from line " << startline - << " to " << stopline << std::endl; - } - } - else { - return ED_PARSER; - } - /* get the current position */ - pos = ftell(ed_cmds); - /* if this is add or change then go to the next full stop */ - if ((mode == MODE_CHANGED) || (mode == MODE_ADDED)) { - do { - fgets(buffer, bufsize, ed_cmds); - while ((strlen(buffer) == (bufsize - 1)) - && (buffer[bufsize - 2] != '\n')) { - fgets(buffer, bufsize, ed_cmds); - buffer[0] = ' '; - } - } while (strncmp(buffer, ".", 1) != 0); - } - /* do the recursive call */ - line = ed_rec(ed_cmds, in_file, out_file, line, buffer, bufsize, - hash); - /* pass on errors */ - if (line < 0) { - return line; - } - /* apply our hunk */ - fseek(ed_cmds, pos, SEEK_SET); - /* first wind to the current position */ - if (mode != MODE_ADDED) { - startline -= 1; - } - while (line < startline) { - fgets(buffer, bufsize, in_file); - written = fwrite(buffer, 1, strlen(buffer), out_file); - hash->Add((unsigned char*)buffer, written); - while ((strlen(buffer) == (bufsize - 1)) - && (buffer[bufsize - 2] != '\n')) { - fgets(buffer, bufsize, in_file); - written = fwrite(buffer, 1, strlen(buffer), out_file); - hash->Add((unsigned char*)buffer, written); - } - line++; - } - /* include from ed script */ - if ((mode == MODE_ADDED) || (mode == MODE_CHANGED)) { - do { - fgets(buffer, bufsize, ed_cmds); - if (strncmp(buffer, ".", 1) != 0) { - written = fwrite(buffer, 1, strlen(buffer), out_file); - hash->Add((unsigned char*)buffer, written); - while ((strlen(buffer) == (bufsize - 1)) - && (buffer[bufsize - 2] != '\n')) { - fgets(buffer, bufsize, ed_cmds); - written = fwrite(buffer, 1, strlen(buffer), out_file); - hash->Add((unsigned char*)buffer, written); - } - } - else { - break; - } - } while (1); - } - /* ignore the corresponding number of lines from input */ - if ((mode == MODE_DELETED) || (mode == MODE_CHANGED)) { - while (line < stopline) { - fgets(buffer, bufsize, in_file); - while ((strlen(buffer) == (bufsize - 1)) - && (buffer[bufsize - 2] != '\n')) { - fgets(buffer, bufsize, in_file); - } - line++; - } - } - return line; -} + // parse in the effected linenumbers + char* idx; + errno=0; + unsigned long const startline = strtol(buffer, &idx, 10); + if (errno == ERANGE || errno == EINVAL) { + _error->Errno("rred", "startline is an invalid number"); + return ED_PARSER; + } + if (startline > line) { + _error->Error("rred: The start line (%lu) of the next command is higher than the last line (%lu). This is not allowed.", startline, line); + return ED_ORDERING; + } + unsigned long stopline; + if (*idx == ',') { + idx++; + errno=0; + stopline = strtol(idx, &idx, 10); + if (errno == ERANGE || errno == EINVAL) { + _error->Errno("rred", "stopline is an invalid number"); + return ED_PARSER; + } + } + else { + stopline = startline; + } + line = startline; + + // which command to execute on this line(s)? + switch (*idx) { + case MODE_CHANGED: + if (Debug == true) + std::clog << "Change from line " << startline << " to " << stopline << std::endl; + break; + case MODE_ADDED: + if (Debug == true) + std::clog << "Insert after line " << startline << std::endl; + break; + case MODE_DELETED: + if (Debug == true) + std::clog << "Delete from line " << startline << " to " << stopline << std::endl; + break; + default: + _error->Error("rred: Unknown ed command '%c'. Abort.", *idx); + return ED_PARSER; + } + unsigned char mode = *idx; + + // save the current position + unsigned const long pos = ftell(ed_cmds); + + // if this is add or change then go to the next full stop + unsigned int data_length = 0; + if (mode == MODE_CHANGED || mode == MODE_ADDED) { + do { + ignoreLineInFile(ed_cmds, buffer); + data_length++; + } + while (strncmp(buffer, ".", 1) != 0); + data_length--; // the dot should not be copied + } + + // do the recursive call - the last command is the one we need to execute at first + const State child = applyFile(ed_cmds, in_file, out_file, line, buffer, hash); + if (child != ED_OK) { + return child; + } + + // change and delete are working on "line" - add is done after "line" + if (mode != MODE_ADDED) + line++; + + // first wind to the current position and copy over all unchanged lines + if (line < startline) { + copyLinesFromFileToFile(in_file, out_file, (startline - line), hash, buffer); + line = startline; + } -int RredMethod::ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, - Hashes *hash) { + if (mode != MODE_ADDED) + line--; + + // include data from ed script + if (mode == MODE_CHANGED || mode == MODE_ADDED) { + fseek(ed_cmds, pos, SEEK_SET); + copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer); + } + + // ignore the corresponding number of lines from input + if (mode == MODE_CHANGED || mode == MODE_DELETED) { + while (line < stopline) { + ignoreLineInFile(in_file, buffer); + line++; + } + } + return ED_OK; +} + /*}}}*/ +void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,/*{{{*/ + Hashes *hash, char *buffer) const { + while (0 < lines--) { + do { + fgets(buffer, BUF_SIZE, fin); + size_t const written = fwrite(buffer, 1, strlen(buffer), fout); + hash->Add((unsigned char*)buffer, written); + } while (strlen(buffer) == (BUF_SIZE - 1) && + buffer[BUF_SIZE - 2] != '\n'); + } +} + /*}}}*/ +void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const { /*{{{*/ + fgets(buffer, BUF_SIZE, fin); + while (strlen(buffer) == (BUF_SIZE - 1) && + buffer[BUF_SIZE - 2] != '\n') { + fgets(buffer, BUF_SIZE, fin); + buffer[0] = ' '; + } +} + /*}}}*/ +RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From, /*{{{*/ + FileFd &out_file, Hashes *hash) const { char buffer[BUF_SIZE]; - int result; - int written; - + FILE* fFrom = fdopen(From.Fd(), "r"); + FILE* fPatch = fdopen(Patch.Fd(), "r"); + FILE* fTo = fdopen(out_file.Fd(), "w"); + /* we do a tail recursion to read the commands in the right order */ - result = ed_rec(ed_cmds, in_file, out_file, 0, buffer, BUF_SIZE, - hash); + unsigned long line = -1; // assign highest possible value + State const result = applyFile(fPatch, fFrom, fTo, line, buffer, hash); /* read the rest from infile */ - if (result >= 0) { - while (fgets(buffer, BUF_SIZE, in_file) != NULL) { - written = fwrite(buffer, 1, strlen(buffer), out_file); + if (result == ED_OK) { + while (fgets(buffer, BUF_SIZE, fFrom) != NULL) { + size_t const written = fwrite(buffer, 1, strlen(buffer), fTo); hash->Add((unsigned char*)buffer, written); } + fflush(fTo); } - else { - return ED_FAILURE; - } - return ED_OK; + return result; } + /*}}}*/ +struct EdCommand { /*{{{*/ + size_t data_start; + size_t data_end; + size_t data_lines; + size_t first_line; + size_t last_line; + char type; +}; +#define IOV_COUNT 1024 /* Don't really want IOV_MAX since it can be arbitrarily large */ + /*}}}*/ +RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ + FileFd &out_file, Hashes *hash) const { +#ifdef _POSIX_MAPPED_FILES + MMap ed_cmds(Patch, MMap::ReadOnly); + MMap in_file(From, MMap::ReadOnly); + + if (ed_cmds.Size() == 0 || in_file.Size() == 0) + return MMAP_FAILED; + + EdCommand* commands = 0; + size_t command_count = 0; + size_t command_alloc = 0; + + const char* begin = (char*) ed_cmds.Data(); + const char* end = begin; + const char* ed_end = (char*) ed_cmds.Data() + ed_cmds.Size(); + + const char* input = (char*) in_file.Data(); + const char* input_end = (char*) in_file.Data() + in_file.Size(); + + size_t i; + + /* 1. Parse entire script. It is executed in reverse order, so we cather it + * in the `commands' buffer first + */ + + for(;;) { + EdCommand cmd; + cmd.data_start = 0; + cmd.data_end = 0; + + while(begin != ed_end && *begin == '\n') + ++begin; + while(end != ed_end && *end != '\n') + ++end; + if(end == ed_end && begin == end) + break; + + /* Determine command range */ + const char* tmp = begin; + + for(;;) { + /* atoll is safe despite lacking NUL-termination; we know there's an + * alphabetic character at end[-1] + */ + if(tmp == end) { + cmd.first_line = atol(begin); + cmd.last_line = cmd.first_line; + break; + } + if(*tmp == ',') { + cmd.first_line = atol(begin); + cmd.last_line = atol(tmp + 1); + break; + } + ++tmp; + } + + // which command to execute on this line(s)? + switch (end[-1]) { + case MODE_CHANGED: + if (Debug == true) + std::clog << "Change from line " << cmd.first_line << " to " << cmd.last_line << std::endl; + break; + case MODE_ADDED: + if (Debug == true) + std::clog << "Insert after line " << cmd.first_line << std::endl; + break; + case MODE_DELETED: + if (Debug == true) + std::clog << "Delete from line " << cmd.first_line << " to " << cmd.last_line << std::endl; + break; + default: + _error->Error("rred: Unknown ed command '%c'. Abort.", end[-1]); + free(commands); + return ED_PARSER; + } + cmd.type = end[-1]; + + /* Determine the size of the inserted text, so we don't have to scan this + * text again later. + */ + begin = end + 1; + end = begin; + cmd.data_lines = 0; + + if(cmd.type == MODE_ADDED || cmd.type == MODE_CHANGED) { + cmd.data_start = begin - (char*) ed_cmds.Data(); + while(end != ed_end) { + if(*end == '\n') { + if(end[-1] == '.' && end[-2] == '\n') + break; + ++cmd.data_lines; + } + ++end; + } + cmd.data_end = end - (char*) ed_cmds.Data() - 1; + begin = end + 1; + end = begin; + } + if(command_count == command_alloc) { + command_alloc = (command_alloc + 64) * 3 / 2; + commands = (EdCommand*) realloc(commands, command_alloc * sizeof(EdCommand)); + } + commands[command_count++] = cmd; + } + + struct iovec* iov = new struct iovec[IOV_COUNT]; + size_t iov_size = 0; + + size_t amount, remaining; + size_t line = 1; + EdCommand* cmd; + + /* 2. Execute script. We gather writes in a `struct iov' array, and flush + * using writev to minimize the number of system calls. Data is read + * directly from the memory mappings of the input file and the script. + */ + + for(i = command_count; i-- > 0; ) { + cmd = &commands[i]; + if(cmd->type == MODE_ADDED) + amount = cmd->first_line + 1; + else + amount = cmd->first_line; + + if(line < amount) { + begin = input; + while(line != amount) { + input = (const char*) memchr(input, '\n', input_end - input); + if(!input) + break; + ++line; + ++input; + } + iov[iov_size].iov_base = (void*) begin; + iov[iov_size].iov_len = input - begin; + hash->Add((const unsigned char*) begin, input - begin); -bool RredMethod::Fetch(FetchItem *Itm) + if(++iov_size == IOV_COUNT) { + writev(out_file.Fd(), iov, IOV_COUNT); + iov_size = 0; + } + } + + if(cmd->type == MODE_DELETED || cmd->type == MODE_CHANGED) { + remaining = (cmd->last_line - cmd->first_line) + 1; + line += remaining; + while(remaining) { + input = (const char*) memchr(input, '\n', input_end - input); + if(!input) + break; + --remaining; + ++input; + } + } + + if(cmd->type == MODE_CHANGED || cmd->type == MODE_ADDED) { + if(cmd->data_end != cmd->data_start) { + iov[iov_size].iov_base = (void*) ((char*)ed_cmds.Data() + cmd->data_start); + iov[iov_size].iov_len = cmd->data_end - cmd->data_start; + hash->Add((const unsigned char*) ((char*)ed_cmds.Data() + cmd->data_start), + iov[iov_size].iov_len); + + if(++iov_size == IOV_COUNT) { + writev(out_file.Fd(), iov, IOV_COUNT); + iov_size = 0; + } + } + } + } + + if(input != input_end) { + iov[iov_size].iov_base = (void*) input; + iov[iov_size].iov_len = input_end - input; + hash->Add((const unsigned char*) input, input_end - input); + ++iov_size; + } + + if(iov_size) { + writev(out_file.Fd(), iov, iov_size); + iov_size = 0; + } + + for(i = 0; i < iov_size; i += IOV_COUNT) { + if(iov_size - i < IOV_COUNT) + writev(out_file.Fd(), iov + i, iov_size - i); + else + writev(out_file.Fd(), iov + i, IOV_COUNT); + } + + delete [] iov; + free(commands); + + return ED_OK; +#else + return MMAP_FAILED; +#endif +} + /*}}}*/ +bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/ { - Debug = _config->FindB("Debug::pkgAcquire::RRed",false); + Debug = _config->FindB("Debug::pkgAcquire::RRed", false); URI Get = Itm->Uri; string Path = Get.Host + Get.Path; // To account for relative paths - // Path contains the filename to patch + FetchResult Res; Res.Filename = Itm->DestFile; - URIStart(Res); - // Res.Filename the destination filename + if (Itm->Uri.empty() == true) { + Path = Itm->DestFile; + Itm->DestFile.append(".result"); + } else + URIStart(Res); if (Debug == true) std::clog << "Patching " << Path << " with " << Path @@ -211,19 +452,27 @@ bool RredMethod::Fetch(FetchItem *Itm) return false; Hashes Hash; - FILE* fFrom = fdopen(From.Fd(), "r"); - FILE* fPatch = fdopen(Patch.Fd(), "r"); - FILE* fTo = fdopen(To.Fd(), "w"); // now do the actual patching - if (ed_file(fPatch, fFrom, fTo, &Hash) != ED_OK) { - _error->Errno("rred", _("Could not patch file")); - return false; + State const result = patchMMap(Patch, From, To, &Hash); + if (result == MMAP_FAILED) { + // retry with patchFile + lseek(Patch.Fd(), 0, SEEK_SET); + lseek(From.Fd(), 0, SEEK_SET); + To.Open(Itm->DestFile,FileFd::WriteEmpty); + if (_error->PendingError() == true) + return false; + if (patchFile(Patch, From, To, &Hash) != ED_OK) { + return _error->WarningE("rred", _("Could not patch %s with mmap and with file operation usage - the patch seems to be corrupt."), Path.c_str()); + } else if (Debug == true) { + std::clog << "rred: finished file patching of " << Path << " after mmap failed." << std::endl; + } + } else if (result != ED_OK) { + return _error->Errno("rred", _("Could not patch %s with mmap (but no mmap specific fail) - the patch seems to be corrupt."), Path.c_str()); + } else if (Debug == true) { + std::clog << "rred: finished mmap patching of " << Path << std::endl; } // write out the result - fflush(fFrom); - fflush(fPatch); - fflush(fTo); From.Close(); Patch.Close(); To.Close(); @@ -250,13 +499,44 @@ bool RredMethod::Fetch(FetchItem *Itm) return true; } - -int main(int argc, char *argv[]) -{ - RredMethod Mth; - - Prog = strrchr(argv[0],'/'); - Prog++; - - return Mth.Run(); + /*}}}*/ +/** \brief Wrapper class for testing rred */ /*{{{*/ +class TestRredMethod : public RredMethod { +public: + /** \brief Run rred in debug test mode + * + * This method can be used to run the rred method outside + * of the "normal" acquire environment for easier testing. + * + * \param base basename of all files involved in this rred test + */ + bool Run(char const *base) { + _config->CndSet("Debug::pkgAcquire::RRed", "true"); + FetchItem *test = new FetchItem; + test->DestFile = base; + return Fetch(test); + } +}; + /*}}}*/ +/** \brief Starter for the rred method (or its test method) {{{ + * + * Used without parameters is the normal behavior for methods for + * the APT acquire system. While this works great for the acquire system + * it is very hard to test the method and therefore the method also + * accepts one parameter which will switch it directly to debug test mode: + * The test mode expects that if "Testfile" is given as parameter + * the file "Testfile" should be ed-style patched with "Testfile.ed" + * and will write the result to "Testfile.result". + */ +int main(int argc, char *argv[]) { + if (argc <= 1) { + RredMethod Mth; + return Mth.Run(); + } else { + TestRredMethod Mth; + bool result = Mth.Run(argv[1]); + _error->DumpErrors(); + return result; + } } + /*}}}*/ -- cgit v1.2.3 From 9f542bae2b3620887345ebc3e61970f8903123a0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 11 Dec 2009 00:32:01 +0100 Subject: add config setting for User-Agent in http and https to the Acquire group, thanks Timothy J. Miller! (Closes: #355782) --- methods/http.cc | 3 ++- methods/https.cc | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'methods') diff --git a/methods/http.cc b/methods/http.cc index 3b210f6b6..2dae87a02 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -731,7 +731,8 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out) Req += string("Authorization: Basic ") + Base64Encode(Uri.User + ":" + Uri.Password) + "\r\n"; } - Req += "User-Agent: Debian APT-HTTP/1.3 ("VERSION")\r\n\r\n"; + Req += "User-Agent: " + _config->Find("Acquire::http::User-Agent", + "Debian APT-HTTP/1.3 ("VERSION")") + "\r\n\r\n"; if (Debug == true) cerr << Req << endl; diff --git a/methods/https.cc b/methods/https.cc index 86d7f3a6b..a4f39c379 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -211,7 +211,10 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit); // set header - curl_easy_setopt(curl, CURLOPT_USERAGENT,"Debian APT-CURL/1.0 ("VERSION")"); + curl_easy_setopt(curl, CURLOPT_USERAGENT, + _config->Find("Acquire::https::User-Agent", + _config->Find("Acquire::http::User-Agent", + "Debian APT-CURL/1.0 ("VERSION")"))); // set timeout int timeout = _config->FindI("Acquire::http::Timeout",120); -- cgit v1.2.3 From b9e9a44b3377cae2fb9aca3210f379ae1cb802ba Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 11 Dec 2009 00:38:13 +0100 Subject: add https options which default to the ones from http for the https method as this is more sane than using only the http options without a possibility to override these for https. --- methods/https.cc | 100 +++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 55 deletions(-) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index a4f39c379..ed1f18150 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -1,4 +1,4 @@ -// -*- mode: cpp; mode: fold -*- +//-*- mode: cpp; mode: fold -*- // Description /*{{{*/ // $Id: http.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $ /* ###################################################################### @@ -57,54 +57,38 @@ HttpsMethod::progress_callback(void *clientp, double dltotal, double dlnow, return 0; } -void HttpsMethod::SetupProxy() -{ - URI ServerName = Queue->Uri; - - // Determine the proxy setting - string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); - if (!SpecificProxy.empty()) - { - if (SpecificProxy == "DIRECT") - Proxy = ""; - else - Proxy = SpecificProxy; - } - else - { - string DefProxy = _config->Find("Acquire::http::Proxy"); - if (!DefProxy.empty()) - { - Proxy = DefProxy; - } - else - { - char* result = getenv("http_proxy"); - Proxy = result ? result : ""; - } - } - - // Parse no_proxy, a , separated list of domains - if (getenv("no_proxy") != 0) - { - if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true) - Proxy = ""; - } - - // Determine what host and port to use based on the proxy settings - string Host; - if (Proxy.empty() == true || Proxy.Host.empty() == true) - { - } - else - { - if (Proxy.Port != 0) - curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port); - curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str()); - } -} - - +void HttpsMethod::SetupProxy() { /*{{{*/ + URI ServerName = Queue->Uri; + + // Determine the proxy setting - try https first, fallback to http and use env at last + string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host, + _config->Find("Acquire::http::Proxy::" + ServerName.Host)); + + if (UseProxy.empty() == true) + UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy")); + + // User want to use NO proxy, so nothing to setup + if (UseProxy == "DIRECT") + return; + + if (UseProxy.empty() == false) { + // Parse no_proxy, a comma (,) separated list of domains we don't want to use + // a proxy for so we stop right here if it is in the list + if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true) + return; + } else { + const char* result = getenv("http_proxy"); + UseProxy = result == NULL ? "" : result; + } + + // Determine what host and port to use based on the proxy settings + if (UseProxy.empty() == false) { + Proxy = UseProxy; + if (Proxy.Port != 1) + curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port); + curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str()); + } +} /*}}}*/ // HttpsMethod::Fetch - Fetch an item /*{{{*/ // --------------------------------------------------------------------- /* This adds an item to the pipeline. We keep the pipeline at a fixed @@ -191,12 +175,15 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version); // cache-control - if(_config->FindB("Acquire::http::No-Cache",false) == false) + if(_config->FindB("Acquire::https::No-Cache", + _config->FindB("Acquire::http::No-Cache",false)) == false) { // cache enabled - if (_config->FindB("Acquire::http::No-Store",false) == true) + if (_config->FindB("Acquire::https::No-Store", + _config->FindB("Acquire::http::No-Store",false)) == true) headers = curl_slist_append(headers,"Cache-Control: no-store"); - ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::http::Max-Age",0)); + ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::https::Max-Age", + _config->FindI("Acquire::http::Max-Age",0))); headers = curl_slist_append(headers, ss.str().c_str()); } else { // cache disabled by user @@ -206,7 +193,8 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // speed limit - int dlLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024; + int dlLimit = _config->FindI("Acquire::https::Dl-Limit", + _config->FindI("Acquire::http::Dl-Limit",0))*1024; if (dlLimit > 0) curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit); @@ -217,14 +205,16 @@ bool HttpsMethod::Fetch(FetchItem *Itm) "Debian APT-CURL/1.0 ("VERSION")"))); // set timeout - int timeout = _config->FindI("Acquire::http::Timeout",120); + int timeout = _config->FindI("Acquire::https::Timeout", + _config->FindI("Acquire::http::Timeout",120)); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); //set really low lowspeed timeout (see #497983) curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout); // set redirect options and default to 10 redirects - bool AllowRedirect = _config->FindI("Acquire::https::AllowRedirect", true); + bool AllowRedirect = _config->FindB("Acquire::https::AllowRedirect", + _config->FindB("Acquire::http::AllowRedirect",true)); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, AllowRedirect); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10); -- cgit v1.2.3 From d746ad6e049c472339003396f934e8ee93a0a378 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 11 Dec 2009 00:42:43 +0100 Subject: add AI_ADDRCONFIG to ai_flags in connect.cc as suggested by Aurelien Jarno in his response to Bernhard R. Link's patch, thanks! (Closes: #505020) --- methods/connect.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'methods') diff --git a/methods/connect.cc b/methods/connect.cc index 74e670ebd..adb16a199 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -158,6 +158,7 @@ bool Connect(string Host,int Port,const char *Service,int DefPort,int &Fd, struct addrinfo Hints; memset(&Hints,0,sizeof(Hints)); Hints.ai_socktype = SOCK_STREAM; + Hints.ai_flags = AI_ADDRCONFIG; Hints.ai_protocol = 0; // if we couldn't resolve the host before, we don't try now -- cgit v1.2.3 From e4c2981b6ecb3c506d8470d4ce39fb8af29339c7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 11 Dec 2009 12:45:04 +0100 Subject: fix the backport of the https methods as they would require an ABI break otherwise in the Configuration class. --- methods/https.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'methods') diff --git a/methods/https.cc b/methods/https.cc index ed1f18150..ad21ef0d3 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -62,10 +62,10 @@ void HttpsMethod::SetupProxy() { /*{{{*/ // Determine the proxy setting - try https first, fallback to http and use env at last string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host, - _config->Find("Acquire::http::Proxy::" + ServerName.Host)); + _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str()); if (UseProxy.empty() == true) - UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy")); + UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy").c_str()); // User want to use NO proxy, so nothing to setup if (UseProxy == "DIRECT") @@ -202,7 +202,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_USERAGENT, _config->Find("Acquire::https::User-Agent", _config->Find("Acquire::http::User-Agent", - "Debian APT-CURL/1.0 ("VERSION")"))); + "Debian APT-CURL/1.0 ("VERSION")").c_str()).c_str()); // set timeout int timeout = _config->FindI("Acquire::https::Timeout", -- cgit v1.2.3 From bf783d9044cb5c9e851fbf10c9bb7e6192b13afd Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Fri, 22 Jan 2010 21:21:30 +0100 Subject: * methods/cdrom.cc: - fixes in multi cdrom setup code --- methods/cdrom.cc | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'methods') diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 9802eb46c..763547013 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -37,8 +37,8 @@ class CDROMMethod : public pkgAcqMethod bool MountedByApt; pkgUdevCdromDevices UdevCdroms; - bool IsCorrectCD(URI want, string MountPath); - bool AutoDetectAndMount(URI); + bool IsCorrectCD(URI want, string MountPath, string& NewID); + bool AutoDetectAndMount(URI, string &NewID); virtual bool Fetch(FetchItem *Itm); string GetID(string Name); virtual void Exit(); @@ -92,7 +92,7 @@ string CDROMMethod::GetID(string Name) // CDROMMethod::AutoDetectAndMount /*{{{*/ // --------------------------------------------------------------------- /* Modifies class varaiable CDROM to the mountpoint */ -bool CDROMMethod::AutoDetectAndMount(URI Get) +bool CDROMMethod::AutoDetectAndMount(URI Get, string NewID) { vector v = UdevCdroms.Scan(); @@ -103,7 +103,7 @@ bool CDROMMethod::AutoDetectAndMount(URI Get) { if (Debug) clog << "Checking mounted cdrom device " << v[i].DeviceName << endl; - if (IsCorrectCD(Get, v[i].MountPath)) + if (IsCorrectCD(Get, v[i].MountPath, NewID)) { CDROM = v[i].MountPath; return true; @@ -126,7 +126,7 @@ bool CDROMMethod::AutoDetectAndMount(URI Get) { if(MountCdrom("/media/apt", v[i].DeviceName)) { - if (IsCorrectCD(Get, "/media/apt")) + if (IsCorrectCD(Get, "/media/apt", NewID)) { MountedByApt = true; CDROM = "/media/apt"; @@ -144,10 +144,8 @@ bool CDROMMethod::AutoDetectAndMount(URI Get) // CDROMMethod::IsCorrectCD /*{{{*/ // --------------------------------------------------------------------- /* */ -bool CDROMMethod::IsCorrectCD(URI want, string MountPath) +bool CDROMMethod::IsCorrectCD(URI want, string MountPath, string& NewID) { - string NewID; - for (unsigned int Version = 2; Version != 0; Version--) { if (IdentCdrom(MountPath,NewID,Version) == false) @@ -226,17 +224,17 @@ bool CDROMMethod::Fetch(FetchItem *Itm) if (CDROM[0] == '.') CDROM= SafeGetCWD() + '/' + CDROM; - string NewID; + string NewID; while (CurrentID.empty() == true) { if (CDROM == "apt-udev-auto/") - AutoDetectAndMount(Get); + AutoDetectAndMount(Get, NewID); if(!IsMounted(CDROM)) MountedByApt = MountCdrom(CDROM); - if (IsCorrectCD(Get, CDROM)) + if (IsCorrectCD(Get, CDROM, NewID)) break; // I suppose this should prompt somehow? -- cgit v1.2.3 From ff1e4b0626d8ce567492ccadbd30dfc32d4c15f1 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 26 Jan 2010 11:27:58 +0100 Subject: add new "Acquire::cdrom::AutoDetect" variable that enables/disables the dlopen of libudev for automatic cdrom detection --- methods/cdrom.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 763547013..87794b052 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -218,6 +218,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm) return true; } + bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true); CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/"); if (Debug) clog << "Looking for CDROM at " << CDROM << endl; @@ -228,7 +229,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm) string NewID; while (CurrentID.empty() == true) { - if (CDROM == "apt-udev-auto/") + if (AutoDetect) AutoDetectAndMount(Get, NewID); if(!IsMounted(CDROM)) -- cgit v1.2.3 From c1f168f54be5b4babeb9b91cd7145441ea2489ad Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 26 Jan 2010 13:37:25 +0100 Subject: methods/cdrom.cc: fix compilication error --- methods/cdrom.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'methods') diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 87794b052..0e78851ff 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -92,7 +92,7 @@ string CDROMMethod::GetID(string Name) // CDROMMethod::AutoDetectAndMount /*{{{*/ // --------------------------------------------------------------------- /* Modifies class varaiable CDROM to the mountpoint */ -bool CDROMMethod::AutoDetectAndMount(URI Get, string NewID) +bool CDROMMethod::AutoDetectAndMount(URI Get, string &NewID) { vector v = UdevCdroms.Scan(); -- cgit v1.2.3