diff options
Diffstat (limited to 'methods')
-rw-r--r-- | methods/http.cc | 33 | ||||
-rw-r--r-- | methods/http.h | 2 | ||||
-rw-r--r-- | methods/makefile | 10 | ||||
-rw-r--r-- | methods/mirror.cc | 95 | ||||
-rw-r--r-- | methods/mirror.h | 2 | ||||
-rw-r--r-- | methods/rred.cc | 17 | ||||
-rw-r--r-- | methods/rsh.cc | 3 |
7 files changed, 140 insertions, 22 deletions
diff --git a/methods/http.cc b/methods/http.cc index dfc1619e3..13f9cbe06 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -778,9 +778,10 @@ bool HttpMethod::Go(bool ToFile,ServerState *Srv) if (Srv->In.WriteSpace() == true && ToFile == true && FileFD != -1) FD_SET(FileFD,&wfds); - + // Add stdin - FD_SET(STDIN_FILENO,&rfds); + if (_config->FindB("Acquire::http::DependOnSTDIN", true) == true) + FD_SET(STDIN_FILENO,&rfds); // Figure out the max fd int MaxFd = FileFD; @@ -947,9 +948,25 @@ HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) && Srv->Result != 304 // Not Modified && Srv->Result != 306)) // (Not part of HTTP/1.1, reserved) { - if (!Srv->Location.empty()) + if (Srv->Location.empty() == true); + else if (Srv->Location[0] == '/' && Queue->Uri.empty() == false) { - NextURI = Srv->Location; + URI Uri = Queue->Uri; + if (Uri.Host.empty() == false) + { + if (Uri.Port != 0) + strprintf(NextURI, "http://%s:%u", Uri.Host.c_str(), Uri.Port); + else + NextURI = "http://" + Uri.Host; + } + else + NextURI.clear(); + NextURI.append(DeQuoteString(Srv->Location)); + return TRY_AGAIN_OR_REDIRECT; + } + else + { + NextURI = DeQuoteString(Srv->Location); return TRY_AGAIN_OR_REDIRECT; } /* else pass through for error message */ @@ -1113,7 +1130,13 @@ int HttpMethod::Loop() do a WaitFd above.. Otherwise the FD is closed. */ int Result = Run(true); if (Result != -1 && (Result != 0 || Queue == 0)) - return 100; + { + if(FailReason.empty() == false || + _config->FindB("Acquire::http::DependOnSTDIN", true) == true) + return 100; + else + return 0; + } if (Queue == 0) continue; diff --git a/methods/http.h b/methods/http.h index 0bc019e77..aa96c6810 100644 --- a/methods/http.h +++ b/methods/http.h @@ -182,7 +182,7 @@ class HttpMethod : public pkgAcqMethod string AutoDetectProxyCmd; public: - friend class ServerState; + friend struct ServerState; FileFd *File; ServerState *Server; diff --git a/methods/makefile b/methods/makefile index 4ee356cec..6ba51058e 100644 --- a/methods/makefile +++ b/methods/makefile @@ -94,8 +94,8 @@ SOURCE = bzip2.cc include $(PROGRAM_H) # SSH and lzma method symlink -binary: $(BIN)/ssh $(BIN)/lzma -veryclean: clean-$(BIN)/ssh clean-$(BIN)/lzma +binary: $(BIN)/ssh $(BIN)/lzma $(BIN)/xz +veryclean: clean-$(BIN)/ssh clean-$(BIN)/lzma clean-$(BIN)/xz $(BIN)/ssh: echo "Installing ssh method link" @@ -108,3 +108,9 @@ $(BIN)/lzma: ln -fs bzip2 $(BIN)/lzma clean-$(BIN)/lzma: -rm $(BIN)/lzma + +$(BIN)/xz: + echo "Installing xz method link" + ln -fs bzip2 $(BIN)/xz +clean-$(BIN)/xz: + -rm $(BIN)/xz diff --git a/methods/mirror.cc b/methods/mirror.cc index e8873d97b..713dc211a 100644 --- a/methods/mirror.cc +++ b/methods/mirror.cc @@ -16,11 +16,15 @@ #include <apt-pkg/hashes.h> #include <apt-pkg/sourcelist.h> + +#include <algorithm> #include <fstream> #include <iostream> + #include <stdarg.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/utsname.h> #include <dirent.h> using namespace std; @@ -125,23 +129,75 @@ bool MirrorMethod::Clean(string Dir) bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str) { - if(Debug) - clog << "MirrorMethod::DownloadMirrorFile(): " << endl; - // not that great to use pkgAcquire here, but we do not have // any other way right now string fetch = BaseUri; fetch.replace(0,strlen("mirror://"),"http://"); + // append the dist as a query string + if (Dist != "") + fetch += "?dist=" + Dist; + + if(Debug) + clog << "MirrorMethod::DownloadMirrorFile(): '" << fetch << "'" + << " to " << MirrorFile << endl; + pkgAcquire Fetcher; new pkgAcqFile(&Fetcher, fetch, "", 0, "", "", "", MirrorFile); bool res = (Fetcher.Run() == pkgAcquire::Continue); - if(res) + if(res) { DownloadedMirrorFile = true; + chmod(MirrorFile.c_str(), 0644); + } Fetcher.Shutdown(); + + if(Debug) + clog << "MirrorMethod::DownloadMirrorFile() success: " << res << endl; + return res; } +// Randomizes the lines in the mirror file, this is used so that +// we spread the load on the mirrors evenly +bool MirrorMethod::RandomizeMirrorFile(string mirror_file) +{ + vector<string> content; + string line; + + if (!FileExists(mirror_file)) + return false; + + // read + ifstream in(mirror_file.c_str()); + while ( !in.eof() ) { + getline(in, line); + content.push_back(line); + } + + // we want the file to be random for each different machine, but also + // "stable" on the same machine. this is to avoid running into out-of-sync + // issues (i.e. Release/Release.gpg different on each mirror) + struct utsname buf; + int seed=1, i; + if(uname(&buf) == 0) { + for(i=0,seed=1; buf.nodename[i] != 0; i++) { + seed = seed * 31 + buf.nodename[i]; + } + } + srand( seed ); + random_shuffle(content.begin(), content.end()); + + // write + ofstream out(mirror_file.c_str()); + while ( !content.empty()) { + line = content.back(); + content.pop_back(); + out << line << "\n"; + } + + return true; +} + /* convert a the Queue->Uri back to the mirror base uri and look * at all mirrors we have for this, this is needed as queue->uri * may point to different mirrors (if TryNextMirror() was run) @@ -176,11 +232,15 @@ bool MirrorMethod::TryNextMirror() continue; vector<string>::const_iterator nextmirror = mirror + 1; - if (nextmirror != AllMirrors.end()) + if (nextmirror == AllMirrors.end()) break; Queue->Uri.replace(0, mirror->length(), *nextmirror); if (Debug) clog << "TryNextMirror: " << Queue->Uri << endl; + + // inform parent + UsedMirror = *nextmirror; + Log("Switching mirror"); return true; } @@ -200,6 +260,13 @@ bool MirrorMethod::InitMirrors() return _error->Error(_("No mirror file '%s' found "), MirrorFile.c_str()); } + if (access(MirrorFile.c_str(), R_OK) != 0) + { + // FIXME: fallback to a default mirror here instead + // and provide a config option to define that default + return _error->Error(_("Can not read mirror file '%s'"), MirrorFile.c_str()); + } + // FIXME: make the mirror selection more clever, do not // just use the first one! // BUT: we can not make this random, the mirror has to be @@ -211,8 +278,18 @@ bool MirrorMethod::InitMirrors() while (!in.eof()) { getline(in, s); - if (s.size() > 0) - AllMirrors.push_back(s); + + // ignore lines that start with # + if (s.find("#") == 0) + continue; + // ignore empty lines + if (s.size() == 0) + continue; + // ignore non http lines + if (s.find("http://") != 0) + continue; + + AllMirrors.push_back(s); } Mirror = AllMirrors[0]; UsedMirror = Mirror; @@ -266,6 +343,7 @@ string MirrorMethod::GetMirrorFileName(string mirror_uri_str) if(Debug) std::cerr << "found BaseURI: " << uristr << std::endl; BaseUri = uristr.substr(0,uristr.size()-1); + Dist = (*I)->GetDist(); } } // get new file @@ -303,7 +381,8 @@ bool MirrorMethod::Fetch(FetchItem *Itm) if(Itm->IndexFile && !DownloadedMirrorFile) { Clean(_config->FindDir("Dir::State::mirrors")); - DownloadMirrorFile(Itm->Uri); + if (DownloadMirrorFile(Itm->Uri)) + RandomizeMirrorFile(MirrorFile); } if(AllMirrors.empty()) { diff --git a/methods/mirror.h b/methods/mirror.h index 0a3ea6e92..97d18144a 100644 --- a/methods/mirror.h +++ b/methods/mirror.h @@ -29,11 +29,13 @@ class MirrorMethod : public HttpMethod vector<string> AllMirrors; // all available mirrors string MirrorFile; // the file that contains the list of mirrors bool DownloadedMirrorFile; // already downloaded this session + string Dist; // the target distrubtion (e.g. sid, oneiric) bool Debug; protected: bool DownloadMirrorFile(string uri); + bool RandomizeMirrorFile(string file); string GetMirrorFileName(string uri); bool InitMirrors(); bool TryNextMirror(); diff --git a/methods/rred.cc b/methods/rred.cc index 1a18a381c..849973e1a 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -252,13 +252,20 @@ struct EdCommand { /*{{{*/ 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 ed_cmds(MMap::ReadOnly); if (Patch.gzFd() != NULL) { unsigned long mapSize = Patch.Size(); - DynamicMMap dyn(0, mapSize, 0); - gzread(Patch.gzFd(), dyn.Data(), mapSize); - ed_cmds = dyn; - } + DynamicMMap* dyn = new DynamicMMap(0, mapSize, 0); + if (dyn->validData() == false) { + delete dyn; + return MMAP_FAILED; + } + dyn->AddSize(mapSize); + gzread(Patch.gzFd(), dyn->Data(), mapSize); + ed_cmds = *dyn; + } else + ed_cmds = MMap(Patch, MMap::ReadOnly); + MMap in_file(From, MMap::ReadOnly); if (ed_cmds.Size() == 0 || in_file.Size() == 0) diff --git a/methods/rsh.cc b/methods/rsh.cc index 97b4ef151..21f0d0a22 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -110,6 +110,8 @@ bool RSHConn::Connect(string Host, string User) // Probably should do // dup2(open("/dev/null",O_RDONLY),STDERR_FILENO); + Args[i++] = Prog; + // Insert user-supplied command line options Configuration::Item const *Opts = RshOptions; if (Opts != 0) @@ -123,7 +125,6 @@ bool RSHConn::Connect(string Host, string User) } } - Args[i++] = Prog; if (User.empty() == false) { Args[i++] = "-l"; Args[i++] = User.c_str(); |