summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
Diffstat (limited to 'methods')
-rw-r--r--methods/bzip2.cc3
-rw-r--r--methods/cdrom.cc2
-rw-r--r--methods/gzip.cc3
-rw-r--r--methods/http.cc50
-rw-r--r--methods/http.h2
-rw-r--r--methods/https.cc6
-rw-r--r--methods/makefile12
-rw-r--r--methods/mirror.cc76
-rw-r--r--methods/mirror.h1
-rw-r--r--methods/rred.cc58
-rw-r--r--methods/rsh.cc3
11 files changed, 177 insertions, 39 deletions
diff --git a/methods/bzip2.cc b/methods/bzip2.cc
index ccc3669a2..42932dded 100644
--- a/methods/bzip2.cc
+++ b/methods/bzip2.cc
@@ -56,9 +56,8 @@ bool Bzip2Method::Fetch(FetchItem *Itm)
// Open the source and destination files
FileFd From(Path,FileFd::ReadOnly);
- // FIXME add an error message saying that empty files can't be valid archives
if(From.FileSize() == 0)
- return false;
+ return _error->Error(_("Empty files can't be valid archives"));
int GzOut[2];
if (pipe(GzOut) < 0)
diff --git a/methods/cdrom.cc b/methods/cdrom.cc
index bf4281e40..b25fdf5a8 100644
--- a/methods/cdrom.cc
+++ b/methods/cdrom.cc
@@ -220,7 +220,7 @@ bool CDROMMethod::Fetch(FetchItem *Itm)
}
bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
- CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
+ CDROM = _config->FindDir("Acquire::cdrom::mount");
if (Debug)
clog << "Looking for CDROM at " << CDROM << endl;
diff --git a/methods/gzip.cc b/methods/gzip.cc
index f1c76066e..fc4e1ecfd 100644
--- a/methods/gzip.cc
+++ b/methods/gzip.cc
@@ -48,9 +48,8 @@ bool GzipMethod::Fetch(FetchItem *Itm)
// Open the source and destination files
FileFd From(Path,FileFd::ReadOnlyGzip);
- // FIXME add an error message saying that empty files can't be valid archives
if(From.FileSize() == 0)
- return false;
+ return _error->Error(_("Empty files can't be valid archives"));
FileFd To(Itm->DestFile,FileFd::WriteAtomic);
To.EraseOnFailure();
diff --git a/methods/http.cc b/methods/http.cc
index 25e31de9a..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)
+ {
+ 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 = Srv->Location;
+ 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;
@@ -1349,9 +1372,10 @@ bool HttpMethod::AutoDetectProxy()
pid_t Process = ExecFork();
if (Process == 0)
{
+ close(Pipes[0]);
dup2(Pipes[1],STDOUT_FILENO);
SetCloseExec(STDOUT_FILENO,false);
-
+
const char *Args[2];
Args[0] = AutoDetectProxyCmd.c_str();
Args[1] = 0;
@@ -1361,10 +1385,18 @@ bool HttpMethod::AutoDetectProxy()
}
char buf[512];
int InFd = Pipes[0];
- if (read(InFd, buf, sizeof(buf)) < 0)
+ close(Pipes[1]);
+ int res = read(InFd, buf, sizeof(buf));
+ ExecWait(Process, "ProxyAutoDetect", true);
+
+ if (res < 0)
return _error->Errno("read", "Failed to read");
- ExecWait(Process, "ProxyAutoDetect");
-
+ if (res == 0)
+ return _error->Warning("ProxyAutoDetect returned no data");
+
+ // add trailing \0
+ buf[res] = 0;
+
if (Debug)
clog << "auto detect command returned: '" << buf << "'" << endl;
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/https.cc b/methods/https.cc
index aa6786aa8..fc649d6c2 100644
--- a/methods/https.cc
+++ b/methods/https.cc
@@ -143,13 +143,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, peer_verify);
// ... and hostname against cert CN or subjectAltName
- int default_verify = 2;
bool verify = _config->FindB("Acquire::https::Verify-Host",true);
knob = "Acquire::https::"+remotehost+"::Verify-Host";
verify = _config->FindB(knob.c_str(),verify);
- if (!verify)
- default_verify = 0;
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verify);
+ int const default_verify = (verify == true) ? 2 : 0;
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, default_verify);
// Also enforce issuer of server certificate using its cert
string issuercert = _config->Find("Acquire::https::IssuerCert","");
diff --git a/methods/makefile b/methods/makefile
index d94a85340..6ba51058e 100644
--- a/methods/makefile
+++ b/methods/makefile
@@ -67,7 +67,7 @@ include $(PROGRAM_H)
# The rred method
PROGRAM=rred
-SLIBS = -lapt-pkg $(SOCKETLIBS) $(INTLLIBS)
+SLIBS = -lapt-pkg -lz $(SOCKETLIBS) $(INTLLIBS)
LIB_MAKES = apt-pkg/makefile
SOURCE = rred.cc
include $(PROGRAM_H)
@@ -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..2cf5c9ce1 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,71 @@ 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://");
+ 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 +228,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 +256,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
@@ -303,7 +366,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..bd807e122 100644
--- a/methods/mirror.h
+++ b/methods/mirror.h
@@ -34,6 +34,7 @@ class MirrorMethod : public HttpMethod
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 d51c45c85..849973e1a 100644
--- a/methods/rred.cc
+++ b/methods/rred.cc
@@ -12,6 +12,7 @@
#include <utime.h>
#include <stdio.h>
#include <errno.h>
+#include <zlib.h>
#include <apti18n.h>
/*}}}*/
/** \brief RredMethod - ed-style incremential patch method {{{
@@ -33,11 +34,14 @@ class RredMethod : public pkgAcqMethod {
// return values
enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED};
- State applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file,
+ State applyFile(gzFile &ed_cmds, FILE *in_file, FILE *out_file,
unsigned long &line, char *buffer, Hashes *hash) const;
void ignoreLineInFile(FILE *fin, char *buffer) const;
+ void ignoreLineInFile(gzFile &fin, char *buffer) const;
void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,
Hashes *hash, char *buffer) const;
+ void copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,
+ Hashes *hash, char *buffer) const;
State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
State patchMMap(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
@@ -65,10 +69,10 @@ public:
* \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,
+RredMethod::State RredMethod::applyFile(gzFile &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 (gzgets(ed_cmds, buffer, BUF_SIZE) == NULL) {
if (Debug == true)
std::clog << "rred: encounter end of file - we can start patching now." << std::endl;
line = 0;
@@ -123,7 +127,7 @@ RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_
unsigned char mode = *idx;
// save the current position
- unsigned const long pos = ftell(ed_cmds);
+ unsigned const long pos = gztell(ed_cmds);
// if this is add or change then go to the next full stop
unsigned int data_length = 0;
@@ -157,7 +161,7 @@ RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_
// include data from ed script
if (mode == MODE_CHANGED || mode == MODE_ADDED) {
- fseek(ed_cmds, pos, SEEK_SET);
+ gzseek(ed_cmds, pos, SEEK_SET);
copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer);
}
@@ -183,6 +187,18 @@ void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lin
}
}
/*}}}*/
+void RredMethod::copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,/*{{{*/
+ Hashes *hash, char *buffer) const {
+ while (0 < lines--) {
+ do {
+ gzgets(fin, buffer, BUF_SIZE);
+ 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) &&
@@ -192,11 +208,20 @@ void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const { /*{{{*/
}
}
/*}}}*/
+void RredMethod::ignoreLineInFile(gzFile &fin, char *buffer) const { /*{{{*/
+ gzgets(fin, buffer, BUF_SIZE);
+ while (strlen(buffer) == (BUF_SIZE - 1) &&
+ buffer[BUF_SIZE - 2] != '\n') {
+ gzgets(fin, buffer, BUF_SIZE);
+ buffer[0] = ' ';
+ }
+}
+ /*}}}*/
RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From, /*{{{*/
FileFd &out_file, Hashes *hash) const {
char buffer[BUF_SIZE];
FILE* fFrom = fdopen(From.Fd(), "r");
- FILE* fPatch = fdopen(Patch.Fd(), "r");
+ gzFile fPatch = Patch.gzFd();
FILE* fTo = fdopen(out_file.Fd(), "w");
/* we do a tail recursion to read the commands in the right order */
@@ -227,7 +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 = 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)
@@ -445,7 +483,7 @@ bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/
// Open the source and destination files (the d'tor of FileFd will do
// the cleanup/closing of the fds)
FileFd From(Path,FileFd::ReadOnly);
- FileFd Patch(Path+".ed",FileFd::ReadOnly);
+ FileFd Patch(Path+".ed",FileFd::ReadOnlyGzip);
FileFd To(Itm->DestFile,FileFd::WriteAtomic);
To.EraseOnFailure();
if (_error->PendingError() == true)
@@ -456,8 +494,8 @@ bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/
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);
+ Patch.Seek(0);
+ From.Seek(0);
To.Open(Itm->DestFile,FileFd::WriteAtomic);
if (_error->PendingError() == true)
return false;
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();