Browse Source
- on gpg verification failure warn and restore the last known good state - on failure display the IP of the server (useful for servers that use round robin DNS) - support Original-Maintainer in RewritePackageOrder - enable cdrom autodetection via libudev by default - show messsage about Vcs in use when apt-get source is run for packages maintained in a Vcs - better support transitional packages with mark auto-installed. when the transitional package is in "oldlibs" the new package is not marked auto installed (same is true for section metapackages) - provide new "deb mirror://archive.foo/mirrors.list sid main" method expects a list of mirrors (generated on the server e.g. via geoip) and will use that, including cycle on failure - write apport crash file on package failure (disabled by default on debian until apport is available) - support mirror failure reporting (disabled by default on debian)debian/1.8.y

38 changed files with 1105 additions and 100 deletions
@ -0,0 +1,29 @@ |
|||
#!/usr/bin/python |
|||
# |
|||
# This is a stub that is meant to support failure reporting of |
|||
# mirrors to a central database |
|||
# |
|||
# its currently not used |
|||
|
|||
import sys |
|||
import urllib |
|||
import apt_pkg |
|||
|
|||
apt_pkg.init() |
|||
url = apt_pkg.Config.find("Acquire::Mirror::ReportFailures", "") |
|||
#"http://people.ubuntu.com:9000/mirror-failure") |
|||
#"http://localhost:9000/mirror-failure") |
|||
if not url: |
|||
sys.exit(0) |
|||
|
|||
print "Reporting mirror failure to '%s'" % url |
|||
|
|||
data = {} |
|||
data['mirror'] = sys.argv[1] |
|||
data['failurl'] = sys.argv[2] |
|||
data['error'] = sys.argv[3] |
|||
f = urllib.urlopen(url, urllib.urlencode(data)) |
|||
f.read() |
|||
f.close() |
|||
|
|||
|
@ -1,9 +1,23 @@ |
|||
APT |
|||
{ |
|||
NeverAutoRemove |
|||
{ |
|||
{ |
|||
"^linux-firmware$"; |
|||
"^linux-image.*"; |
|||
"^linux-restricted-modules.*"; |
|||
"^kfreebsd-image.*"; |
|||
"^linux-ubuntu-modules-.*"; |
|||
}; |
|||
|
|||
Never-MarkAuto-Sections |
|||
{ |
|||
"metapackages"; |
|||
"restricted/metapackages"; |
|||
"universe/metapackages"; |
|||
"multiverse/metapackages"; |
|||
"oldlibs"; |
|||
"restricted/oldlibs"; |
|||
"universe/oldlibs"; |
|||
"multiverse/oldlibs"; |
|||
|
|||
}; |
|||
}; |
|||
|
@ -0,0 +1,20 @@ |
|||
#include <apt-pkg/fileutl.h> |
|||
#include <apt-pkg/acquire-method.h> |
|||
#include <signal.h> |
|||
|
|||
#include "connect.h" |
|||
#include "rfc2553emu.h" |
|||
#include "http.h" |
|||
|
|||
|
|||
int main() |
|||
{ |
|||
setlocale(LC_ALL, ""); |
|||
|
|||
// ignore SIGPIPE, this can happen on write() if the socket
|
|||
// closes the connection (this is dealt with via ServerDie())
|
|||
signal(SIGPIPE, SIG_IGN); |
|||
|
|||
HttpMethod Mth; |
|||
return Mth.Loop(); |
|||
} |
@ -0,0 +1,330 @@ |
|||
// -*- mode: cpp; mode: fold -*-
|
|||
// Description /*{{{*/
|
|||
// $Id: mirror.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $
|
|||
/* ######################################################################
|
|||
|
|||
Mirror Aquire Method - This is the Mirror aquire method for APT. |
|||
|
|||
##################################################################### */ |
|||
/*}}}*/ |
|||
// Include Files /*{{{*/
|
|||
#include <apt-pkg/fileutl.h> |
|||
#include <apt-pkg/acquire-method.h> |
|||
#include <apt-pkg/acquire-item.h> |
|||
#include <apt-pkg/acquire.h> |
|||
#include <apt-pkg/error.h> |
|||
#include <apt-pkg/hashes.h> |
|||
#include <apt-pkg/sourcelist.h> |
|||
|
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <stdarg.h> |
|||
#include <sys/stat.h> |
|||
#include <sys/types.h> |
|||
#include <dirent.h> |
|||
|
|||
using namespace std; |
|||
|
|||
#include "mirror.h" |
|||
#include "http.h" |
|||
#include "apti18n.h" |
|||
/*}}}*/ |
|||
|
|||
/* Done:
|
|||
* - works with http (only!) |
|||
* - always picks the first mirror from the list |
|||
* - call out to problem reporting script |
|||
* - supports "deb mirror://host/path/to/mirror-list/// dist component" |
|||
* - uses pkgAcqMethod::FailReason() to have a string representation |
|||
* of the failure that is also send to LP |
|||
* |
|||
* TODO: |
|||
* - deal with runing as non-root because we can't write to the lists |
|||
dir then -> use the cached mirror file |
|||
* - better method to download than having a pkgAcquire interface here |
|||
* and better error handling there! |
|||
* - support more than http |
|||
* - testing :) |
|||
*/ |
|||
|
|||
MirrorMethod::MirrorMethod() |
|||
: HttpMethod(), DownloadedMirrorFile(false) |
|||
{ |
|||
}; |
|||
|
|||
// HttpMethod::Configuration - Handle a configuration message /*{{{*/
|
|||
// ---------------------------------------------------------------------
|
|||
/* We stash the desired pipeline depth */ |
|||
bool MirrorMethod::Configuration(string Message) |
|||
{ |
|||
if (pkgAcqMethod::Configuration(Message) == false) |
|||
return false; |
|||
Debug = _config->FindB("Debug::Acquire::mirror",false); |
|||
|
|||
return true; |
|||
} |
|||
/*}}}*/ |
|||
|
|||
// clean the mirrors dir based on ttl information
|
|||
bool MirrorMethod::Clean(string Dir) |
|||
{ |
|||
vector<metaIndex *>::const_iterator I; |
|||
|
|||
if(Debug) |
|||
clog << "MirrorMethod::Clean(): " << Dir << endl; |
|||
|
|||
if(Dir == "/") |
|||
return _error->Error("will not clean: '/'"); |
|||
|
|||
// read sources.list
|
|||
pkgSourceList list; |
|||
list.ReadMainList(); |
|||
|
|||
DIR *D = opendir(Dir.c_str()); |
|||
if (D == 0) |
|||
return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str()); |
|||
|
|||
string StartDir = SafeGetCWD(); |
|||
if (chdir(Dir.c_str()) != 0) |
|||
{ |
|||
closedir(D); |
|||
return _error->Errno("chdir",_("Unable to change to %s"),Dir.c_str()); |
|||
} |
|||
|
|||
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) |
|||
{ |
|||
// Skip some files..
|
|||
if (strcmp(Dir->d_name,"lock") == 0 || |
|||
strcmp(Dir->d_name,"partial") == 0 || |
|||
strcmp(Dir->d_name,".") == 0 || |
|||
strcmp(Dir->d_name,"..") == 0) |
|||
continue; |
|||
|
|||
// see if we have that uri
|
|||
for(I=list.begin(); I != list.end(); I++) |
|||
{ |
|||
string uri = (*I)->GetURI(); |
|||
if(uri.substr(0,strlen("mirror://")) != string("mirror://")) |
|||
continue; |
|||
string BaseUri = uri.substr(0,uri.size()-1); |
|||
if (URItoFileName(BaseUri) == Dir->d_name) |
|||
break; |
|||
} |
|||
// nothing found, nuke it
|
|||
if (I == list.end()) |
|||
unlink(Dir->d_name); |
|||
}; |
|||
|
|||
chdir(StartDir.c_str()); |
|||
closedir(D); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str) |
|||
{ |
|||
if(Debug) |
|||
clog << "MirrorMethod::DownloadMirrorFile(): " << endl; |
|||
|
|||
// check the file, if it is not older than RefreshInterval just use it
|
|||
// otherwise try to get a new one
|
|||
if(FileExists(MirrorFile)) |
|||
{ |
|||
struct stat buf; |
|||
time_t t,now,refresh; |
|||
if(stat(MirrorFile.c_str(), &buf) != 0) |
|||
return false; |
|||
t = std::max(buf.st_mtime, buf.st_ctime); |
|||
now = time(NULL); |
|||
refresh = 60*_config->FindI("Acquire::Mirror::RefreshInterval",360); |
|||
if(t + refresh > now) |
|||
{ |
|||
if(Debug) |
|||
clog << "Mirror file is in RefreshInterval" << endl; |
|||
DownloadedMirrorFile = true; |
|||
return true; |
|||
} |
|||
if(Debug) |
|||
clog << "Mirror file " << MirrorFile << " older than " << refresh << "min, re-download it" << 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://"); |
|||
|
|||
pkgAcquire Fetcher; |
|||
new pkgAcqFile(&Fetcher, fetch, "", 0, "", "", "", MirrorFile); |
|||
bool res = (Fetcher.Run() == pkgAcquire::Continue); |
|||
if(res) |
|||
DownloadedMirrorFile = true; |
|||
Fetcher.Shutdown(); |
|||
return res; |
|||
} |
|||
|
|||
bool MirrorMethod::SelectMirror() |
|||
{ |
|||
// if we do not have a MirrorFile, fallback
|
|||
if(!FileExists(MirrorFile)) |
|||
{ |
|||
// FIXME: fallback to a default mirror here instead
|
|||
// and provide a config option to define that default
|
|||
return _error->Error(_("No mirror file '%s' found "), 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
|
|||
// stable accross session, because otherwise we can
|
|||
// get into sync issues (got indexfiles from mirror A,
|
|||
// but packages from mirror B - one might be out of date etc)
|
|||
ifstream in(MirrorFile.c_str()); |
|||
getline(in, Mirror); |
|||
if(Debug) |
|||
cerr << "Using mirror: " << Mirror << endl; |
|||
|
|||
UsedMirror = Mirror; |
|||
return true; |
|||
} |
|||
|
|||
string MirrorMethod::GetMirrorFileName(string mirror_uri_str) |
|||
{ |
|||
/*
|
|||
- a mirror_uri_str looks like this: |
|||
mirror://people.ubuntu.com/~mvo/apt/mirror/mirrors/dists/feisty/Release.gpg
|
|||
|
|||
- the matching source.list entry |
|||
deb mirror://people.ubuntu.com/~mvo/apt/mirror/mirrors feisty main
|
|||
|
|||
- we actually want to go after: |
|||
http://people.ubuntu.com/~mvo/apt/mirror/mirrors
|
|||
|
|||
And we need to save the BaseUri for later: |
|||
- mirror://people.ubuntu.com/~mvo/apt/mirror/mirrors
|
|||
|
|||
FIXME: what if we have two similar prefixes? |
|||
mirror://people.ubuntu.com/~mvo/mirror
|
|||
mirror://people.ubuntu.com/~mvo/mirror2
|
|||
then mirror_uri_str looks like: |
|||
mirror://people.ubuntu.com/~mvo/apt/mirror/dists/feisty/Release.gpg
|
|||
mirror://people.ubuntu.com/~mvo/apt/mirror2/dists/feisty/Release.gpg
|
|||
we search sources.list and find: |
|||
mirror://people.ubuntu.com/~mvo/apt/mirror
|
|||
in both cases! So we need to apply some domain knowledge here :( and |
|||
check for /dists/ or /Release.gpg as suffixes |
|||
*/ |
|||
string name; |
|||
if(Debug) |
|||
std::cerr << "GetMirrorFileName: " << mirror_uri_str << std::endl; |
|||
|
|||
// read sources.list and find match
|
|||
vector<metaIndex *>::const_iterator I; |
|||
pkgSourceList list; |
|||
list.ReadMainList(); |
|||
for(I=list.begin(); I != list.end(); I++) |
|||
{ |
|||
string uristr = (*I)->GetURI(); |
|||
if(Debug) |
|||
std::cerr << "Checking: " << uristr << std::endl; |
|||
if(uristr.substr(0,strlen("mirror://")) != string("mirror://")) |
|||
continue; |
|||
// find matching uri in sources.list
|
|||
if(mirror_uri_str.substr(0,uristr.size()) == uristr) |
|||
{ |
|||
if(Debug) |
|||
std::cerr << "found BaseURI: " << uristr << std::endl; |
|||
BaseUri = uristr.substr(0,uristr.size()-1); |
|||
} |
|||
} |
|||
// get new file
|
|||
name = _config->FindDir("Dir::State::mirrors") + URItoFileName(BaseUri); |
|||
|
|||
if(Debug) |
|||
{ |
|||
cerr << "base-uri: " << BaseUri << endl; |
|||
cerr << "mirror-file: " << name << endl; |
|||
} |
|||
return name; |
|||
} |
|||
|
|||
// MirrorMethod::Fetch - Fetch an item /*{{{*/
|
|||
// ---------------------------------------------------------------------
|
|||
/* This adds an item to the pipeline. We keep the pipeline at a fixed
|
|||
depth. */ |
|||
bool MirrorMethod::Fetch(FetchItem *Itm) |
|||
{ |
|||
if(Debug) |
|||
clog << "MirrorMethod::Fetch() |