]> git.saurik.com Git - apt.git/blob - methods/mirror.cc
e70a40f55bf6c2bd8d35ae33399ea822f7947944
[apt.git] / methods / mirror.cc
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>
20 #include <stdarg.h>
21 #include <sys/stat.h>
22
23 using namespace std;
24
25 #include "mirror.h"
26 #include "http.h"
27
28 /*}}}*/
29
30 /*
31 * TODO:
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
40 * - better method to download than having a pkgAcquire interface here
41 * - magicmarker is (a bit) evil
42 * - testing :)
43 */
44
45 MirrorMethod::MirrorMethod()
46 : HttpMethod(), HasMirrorFile(false)
47 {
48 #if 0
49 HasMirrorFile=true;
50 BaseUri="mirror://people.ubuntu.com/~mvo/mirror/mirrors";
51 MirrorFile="/var/lib/apt/lists/people.ubuntu.com_%7emvo_apt_mirror_mirrors";
52 Mirror="http://de.archive.ubuntu.com/ubuntu/";
53 #endif
54 };
55
56 // HttpMethod::Configuration - Handle a configuration message /*{{{*/
57 // ---------------------------------------------------------------------
58 /* We stash the desired pipeline depth */
59 bool 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
69 // clean the mirrors dir based on ttl information
70 bool MirrorMethod::Clean(string dir)
71 {
72
73 }
74
75
76 bool MirrorMethod::GetMirrorFile(string uri)
77 {
78 string Marker = _config->Find("Acquire::Mirror::MagicMarker","///");
79 BaseUri = uri.substr(0,uri.find(Marker));
80
81 string fetch = BaseUri;
82 fetch.replace(0,strlen("mirror://"),"http://");
83
84 MirrorFile = _config->FindDir("Dir::State::mirrors") + URItoFileName(BaseUri);
85
86 if(Debug)
87 {
88 cerr << "base-uri: " << BaseUri << endl;
89 cerr << "mirror-file: " << MirrorFile << endl;
90 }
91
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
116 pkgAcquire Fetcher;
117 new pkgAcqFile(&Fetcher, fetch, "", 0, "", "", "", MirrorFile);
118 bool res = (Fetcher.Run() == pkgAcquire::Continue);
119 if(res)
120 HasMirrorFile = true;
121 Fetcher.Shutdown();
122 return res;
123 }
124
125 bool MirrorMethod::SelectMirror()
126 {
127 // FIXME: make the mirror selection more clever, do not
128 // just use the first one!
129 ifstream in(MirrorFile.c_str());
130 getline(in, Mirror);
131 if(Debug)
132 cerr << "Using mirror: " << Mirror << endl;
133 return true;
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. */
140 bool MirrorMethod::Fetch(FetchItem *Itm)
141 {
142 // select mirror only once per session
143 if(!HasMirrorFile)
144 {
145 GetMirrorFile(Itm->Uri);
146 SelectMirror();
147 }
148
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 }
154
155 // now run the real fetcher
156 return HttpMethod::Fetch(Itm);
157 };
158
159 void 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
166 void 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
173 void 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
181 int main()
182 {
183 setlocale(LC_ALL, "");
184
185 MirrorMethod Mth;
186
187 return Mth.Loop();
188 }
189
190