* apt-pkg/init.cc:
[ntk/apt.git] / methods / mirror.cc
CommitLineData
5f6b130d
MV
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: mirror.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $
4/* ######################################################################
5
6 Mirror Aquire Method - This is the Mirror aquire method for APT.
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
11#include <apt-pkg/fileutl.h>
12#include <apt-pkg/acquire-method.h>
13#include <apt-pkg/acquire-item.h>
14#include <apt-pkg/acquire.h>
15#include <apt-pkg/error.h>
16#include <apt-pkg/hashes.h>
17
18#include <fstream>
19#include <iostream>
14e097c1 20#include <stdarg.h>
d731f9c5 21#include <sys/stat.h>
14e097c1 22
5f6b130d
MV
23using namespace std;
24
25#include "mirror.h"
26#include "http.h"
27
28 /*}}}*/
29
86c17f0a
MV
30/*
31 * TODO:
d731f9c5
MV
32 * - send expected checksum to the mirror method so that
33 some checking/falling back can be done here already
34 * - keep the mirror file around in /var/lib/apt/mirrors
35 * can't be put into lists/ because of the listclearer
36 * cleanup by time (mtime relative to the other mtimes)
37 * - use a TTL time the mirror file is fetched again (6h?)
38 * - deal with runing as non-root because we can't write to the lists
39 dir then -> use the cached mirror file
86c17f0a 40 * - better method to download than having a pkgAcquire interface here
d731f9c5 41 * - magicmarker is (a bit) evil
86c17f0a 42 * - testing :)
86c17f0a
MV
43 */
44
5f6b130d 45MirrorMethod::MirrorMethod()
14e097c1 46 : HttpMethod(), HasMirrorFile(false)
5f6b130d
MV
47{
48#if 0
49 HasMirrorFile=true;
14e097c1
MV
50 BaseUri="mirror://people.ubuntu.com/~mvo/mirror/mirrors";
51 MirrorFile="/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_mirror_mirrors";
5f6b130d
MV
52 Mirror="http://de.archive.ubuntu.com/ubuntu/";
53#endif
54};
55
14e097c1
MV
56// HttpMethod::Configuration - Handle a configuration message /*{{{*/
57// ---------------------------------------------------------------------
58/* We stash the desired pipeline depth */
59bool MirrorMethod::Configuration(string Message)
60{
61 if (pkgAcqMethod::Configuration(Message) == false)
62 return false;
63 Debug = _config->FindB("Debug::Acquire::mirror",false);
64
65 return true;
66}
67 /*}}}*/
68
d731f9c5
MV
69// clean the mirrors dir based on ttl information
70bool MirrorMethod::Clean(string dir)
71{
72
73}
74
14e097c1 75
5f6b130d
MV
76bool MirrorMethod::GetMirrorFile(string uri)
77{
78 string Marker = _config->Find("Acquire::Mirror::MagicMarker","///");
79 BaseUri = uri.substr(0,uri.find(Marker));
14e097c1
MV
80
81 string fetch = BaseUri;
82 fetch.replace(0,strlen("mirror://"),"http://");
5f6b130d 83
d731f9c5 84 MirrorFile = _config->FindDir("Dir::State::mirrors") + URItoFileName(BaseUri);
5f6b130d 85
14e097c1
MV
86 if(Debug)
87 {
88 cerr << "base-uri: " << BaseUri << endl;
89 cerr << "mirror-file: " << MirrorFile << endl;
90 }
5f6b130d 91
d731f9c5
MV
92 // check the file, if it is not older than RefreshInterval just use it
93 // otherwise try to get a new one
94 if(FileExists(MirrorFile))
95 {
96 struct stat buf;
97 time_t t,now,refresh;
98 if(stat(MirrorFile.c_str(), &buf) != 0)
99 return false;
100 t = std::max(buf.st_mtime, buf.st_ctime);
101 now = time(NULL);
102 refresh = 60*_config->FindI("Acquire::Mirror::RefreshInterval",360);
103 if(t + refresh > now)
104 {
105 if(Debug)
106 clog << "Mirror file is in RefreshInterval" << endl;
107 HasMirrorFile = true;
108 return true;
109 }
110 if(Debug)
111 clog << "Mirror file " << MirrorFile << " older than " << refresh << ", re-download it" << endl;
112 }
113
114 // not that great to use pkgAcquire here, but we do not have
115 // any other way right now
5f6b130d 116 pkgAcquire Fetcher;
14e097c1 117 new pkgAcqFile(&Fetcher, fetch, "", 0, "", "", "", MirrorFile);
5f6b130d 118 bool res = (Fetcher.Run() == pkgAcquire::Continue);
d731f9c5 119 if(res)
5f6b130d
MV
120 HasMirrorFile = true;
121 Fetcher.Shutdown();
d731f9c5 122 return res;
5f6b130d
MV
123}
124
125bool MirrorMethod::SelectMirror()
126{
d731f9c5
MV
127 // FIXME: make the mirror selection more clever, do not
128 // just use the first one!
5f6b130d
MV
129 ifstream in(MirrorFile.c_str());
130 getline(in, Mirror);
14e097c1
MV
131 if(Debug)
132 cerr << "Using mirror: " << Mirror << endl;
133 return true;
5f6b130d
MV
134}
135
136// MirrorMethod::Fetch - Fetch an item /*{{{*/
137// ---------------------------------------------------------------------
138/* This adds an item to the pipeline. We keep the pipeline at a fixed
139 depth. */
140bool MirrorMethod::Fetch(FetchItem *Itm)
141{
d731f9c5 142 // select mirror only once per session
5f6b130d
MV
143 if(!HasMirrorFile)
144 {
145 GetMirrorFile(Itm->Uri);
146 SelectMirror();
147 }
148
ef1e6d88
MV
149 for (FetchItem *I = Queue; I != 0; I = I->Next)
150 {
151 if(I->Uri.find("mirror://") != string::npos)
152 I->Uri.replace(0,BaseUri.size(),Mirror);
153 }
5f6b130d 154
14e097c1
MV
155 // now run the real fetcher
156 return HttpMethod::Fetch(Itm);
5f6b130d
MV
157};
158
14e097c1
MV
159void MirrorMethod::Fail(string Err,bool Transient)
160{
161 if(Queue->Uri.find("http://") != string::npos)
162 Queue->Uri.replace(0,Mirror.size(), BaseUri);
163 pkgAcqMethod::Fail(Err, Transient);
164}
165
166void MirrorMethod::URIStart(FetchResult &Res)
167{
168 if(Queue->Uri.find("http://") != string::npos)
169 Queue->Uri.replace(0,Mirror.size(), BaseUri);
170 pkgAcqMethod::URIStart(Res);
171}
172
173void MirrorMethod::URIDone(FetchResult &Res,FetchResult *Alt)
174{
175 if(Queue->Uri.find("http://") != string::npos)
176 Queue->Uri.replace(0,Mirror.size(), BaseUri);
177 pkgAcqMethod::URIDone(Res, Alt);
178}
179
180
5f6b130d
MV
181int main()
182{
183 setlocale(LC_ALL, "");
184
185 MirrorMethod Mth;
186
14e097c1 187 return Mth.Loop();
5f6b130d
MV
188}
189
190