]> git.saurik.com Git - apt.git/blame - apt-pkg/aptconfiguration.cc
merged from debian-sid
[apt.git] / apt-pkg / aptconfiguration.cc
CommitLineData
e878aedb
DK
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3/* ######################################################################
4
5 Provide access methods to various configuration settings,
6 setup defaults and returns validate settings.
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
e878aedb
DK
11#include <apt-pkg/aptconfiguration.h>
12#include <apt-pkg/configuration.h>
9f9717fa 13#include <apt-pkg/error.h>
d7cf5923
DK
14#include <apt-pkg/fileutl.h>
15#include <apt-pkg/macros.h>
16#include <apt-pkg/strutl.h>
e878aedb 17
3f2d77b5
DK
18#include <sys/types.h>
19#include <dirent.h>
20
8bd02d8b 21#include <algorithm>
3f2d77b5
DK
22#include <string>
23#include <vector>
e878aedb
DK
24 /*}}}*/
25namespace APT {
26// getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/
27// ---------------------------------------------------------------------
28/* return a vector of compression types in the prefered order. */
29std::vector<std::string>
30const Configuration::getCompressionTypes(bool const &Cached) {
31 static std::vector<std::string> types;
32 if (types.empty() == false) {
33 if (Cached == true)
34 return types;
35 else
36 types.clear();
37 }
38
8bd02d8b
DK
39 // setup the defaults for the compressiontypes => method mapping
40 _config->CndSet("Acquire::CompressionTypes::bz2","bzip2");
b2430e6d 41 _config->CndSet("Acquire::CompressionTypes::xz","xz");
8bd02d8b
DK
42 _config->CndSet("Acquire::CompressionTypes::lzma","lzma");
43 _config->CndSet("Acquire::CompressionTypes::gz","gzip");
44
03bef784 45 setDefaultConfigurationForCompressors();
e878aedb 46
8bd02d8b
DK
47 // accept non-list order as override setting for config settings on commandline
48 std::string const overrideOrder = _config->Find("Acquire::CompressionTypes::Order","");
49 if (overrideOrder.empty() == false)
50 types.push_back(overrideOrder);
e878aedb 51
8bd02d8b
DK
52 // load the order setting into our vector
53 std::vector<std::string> const order = _config->FindVector("Acquire::CompressionTypes::Order");
54 for (std::vector<std::string>::const_iterator o = order.begin();
55 o != order.end(); o++) {
56 if ((*o).empty() == true)
57 continue;
58 // ignore types we have no method ready to use
59 if (_config->Exists(string("Acquire::CompressionTypes::").append(*o)) == false)
60 continue;
61 // ignore types we have no app ready to use
62 string const appsetting = string("Dir::Bin::").append(*o);
63 if (_config->Exists(appsetting) == true) {
64 std::string const app = _config->FindFile(appsetting.c_str(), "");
65 if (app.empty() == false && FileExists(app) == false)
66 continue;
67 }
68 types.push_back(*o);
e878aedb
DK
69 }
70
8bd02d8b 71 // move again over the option tree to add all missing compression types
e878aedb
DK
72 ::Configuration::Item const *Types = _config->Tree("Acquire::CompressionTypes");
73 if (Types != 0)
74 Types = Types->Child;
75
76 for (; Types != 0; Types = Types->Next) {
8bd02d8b
DK
77 if (Types->Tag == "Order" || Types->Tag.empty() == true)
78 continue;
79 // ignore types we already have in the vector
80 if (std::find(types.begin(),types.end(),Types->Tag) != types.end())
81 continue;
82 // ignore types we have no app ready to use
e878aedb 83 string const appsetting = string("Dir::Bin::").append(Types->Value);
e878aedb
DK
84 if (appsetting.empty() == false && _config->Exists(appsetting) == true) {
85 std::string const app = _config->FindFile(appsetting.c_str(), "");
86 if (app.empty() == false && FileExists(app) == false)
87 continue;
88 }
89 types.push_back(Types->Tag);
90 }
91
5d885723
DK
92 // add the special "uncompressed" type
93 if (std::find(types.begin(), types.end(), "uncompressed") == types.end())
94 {
95 string const uncompr = _config->FindFile("Dir::Bin::uncompressed", "");
96 if (uncompr.empty() == true || FileExists(uncompr) == true)
97 types.push_back("uncompressed");
98 }
99
e878aedb
DK
100 return types;
101}
102 /*}}}*/
45df0ad2
DK
103// GetLanguages - Return Vector of Language Codes /*{{{*/
104// ---------------------------------------------------------------------
105/* return a vector of language codes in the prefered order.
106 the special word "environment" will be replaced with the long and the short
107 code of the local settings and it will be insured that this will not add
108 duplicates. So in an german local the setting "environment, de_DE, en, de"
109 will result in "de_DE, de, en".
110 The special word "none" is the stopcode for the not-All code vector */
111std::vector<std::string> const Configuration::getLanguages(bool const &All,
d7cf5923 112 bool const &Cached, char const ** const Locale) {
45df0ad2
DK
113 using std::string;
114
115 // The detection is boring and has a lot of cornercases,
116 // so we cache the results to calculated it only once.
117 std::vector<string> static allCodes;
118 std::vector<string> static codes;
119
120 // we have something in the cache
121 if (codes.empty() == false || allCodes.empty() == false) {
122 if (Cached == true) {
123 if(All == true && allCodes.empty() == false)
124 return allCodes;
125 else
126 return codes;
127 } else {
128 allCodes.clear();
129 codes.clear();
130 }
131 }
132
3f2d77b5
DK
133 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
134 // so they will be all included in the Cache.
135 std::vector<string> builtin;
136 DIR *D = opendir(_config->FindDir("Dir::State::lists").c_str());
137 if (D != 0) {
138 builtin.push_back("none");
139 for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) {
140 string const name = Ent->d_name;
141 size_t const foundDash = name.rfind("-");
142 size_t const foundUnderscore = name.rfind("_");
143 if (foundDash == string::npos || foundUnderscore == string::npos ||
144 foundDash <= foundUnderscore ||
145 name.substr(foundUnderscore+1, foundDash-(foundUnderscore+1)) != "Translation")
146 continue;
147 string const c = name.substr(foundDash+1);
148 if (unlikely(c.empty() == true) || c == "en")
149 continue;
150 // Skip unusual files, like backups or that alike
151 string::const_iterator s = c.begin();
152 for (;s != c.end(); ++s) {
153 if (isalpha(*s) == 0)
154 break;
155 }
156 if (s != c.end())
157 continue;
158 if (std::find(builtin.begin(), builtin.end(), c) != builtin.end())
159 continue;
160 builtin.push_back(c);
161 }
162 }
cf0e078c 163 closedir(D);
3f2d77b5 164
45df0ad2
DK
165 // FIXME: Remove support for the old APT::Acquire::Translation
166 // it was undocumented and so it should be not very widthly used
167 string const oldAcquire = _config->Find("APT::Acquire::Translation","");
168 if (oldAcquire.empty() == false && oldAcquire != "environment") {
9f9717fa
DK
169 // TRANSLATORS: the two %s are APT configuration options
170 _error->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
171 "APT::Acquire::Translation", "Acquire::Languages");
45df0ad2
DK
172 if (oldAcquire != "none")
173 codes.push_back(oldAcquire);
3f2d77b5 174 codes.push_back("en");
d7cf5923 175 allCodes = codes;
3f2d77b5
DK
176 for (std::vector<string>::const_iterator b = builtin.begin();
177 b != builtin.end(); ++b)
178 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
179 allCodes.push_back(*b);
180 if (All == true)
181 return allCodes;
182 else
183 return codes;
45df0ad2
DK
184 }
185
ab53c018
DK
186 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
187 // we extract both, a long and a short code and then we will
188 // check if we actually need both (rare) or if the short is enough
189 string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale);
190 size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
191 size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3);
192
193 string const envLong = envMsg.substr(0,lenLong);
194 string const envShort = envLong.substr(0,lenShort);
195
196 // It is very likely we will need the environment codes later,
d7cf5923
DK
197 // so let us generate them now from LC_MESSAGES and LANGUAGE
198 std::vector<string> environment;
eb3947c6
DK
199 if (envShort != "C") {
200 // take care of LC_MESSAGES
ab53c018 201 if (envLong != envShort)
eb3947c6
DK
202 environment.push_back(envLong);
203 environment.push_back(envShort);
204 // take care of LANGUAGE
205 const char *language_env = getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
206 string envLang = Locale == 0 ? language_env : *(Locale+1);
207 if (envLang.empty() == false) {
208 std::vector<string> env = VectorizeString(envLang,':');
209 short addedLangs = 0; // add a maximum of 3 fallbacks from the environment
210 for (std::vector<string>::const_iterator e = env.begin();
211 e != env.end() && addedLangs < 3; ++e) {
212 if (unlikely(e->empty() == true) || *e == "en")
213 continue;
214 if (*e == envLong || *e == envShort)
215 continue;
216 if (std::find(environment.begin(), environment.end(), *e) != environment.end())
d7cf5923 217 continue;
eb3947c6
DK
218 ++addedLangs;
219 environment.push_back(*e);
d7cf5923 220 }
d7cf5923 221 }
eb3947c6
DK
222 } else {
223 environment.push_back("en");
d7cf5923
DK
224 }
225
45df0ad2
DK
226 // Support settings like Acquire::Translation=none on the command line to
227 // override the configuration settings vector of languages.
228 string const forceLang = _config->Find("Acquire::Languages","");
229 if (forceLang.empty() == false) {
230 if (forceLang == "environment") {
d7cf5923 231 codes = environment;
45df0ad2
DK
232 } else if (forceLang != "none")
233 codes.push_back(forceLang);
d7cf5923 234 allCodes = codes;
3f2d77b5
DK
235 for (std::vector<string>::const_iterator b = builtin.begin();
236 b != builtin.end(); ++b)
237 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
238 allCodes.push_back(*b);
239 if (All == true)
240 return allCodes;
241 else
242 return codes;
45df0ad2
DK
243 }
244
eb3947c6
DK
245 // cornercase: LANG=C, so we use only "en" Translation
246 if (envShort == "C") {
247 allCodes = codes = environment;
248 allCodes.insert(allCodes.end(), builtin.begin(), builtin.end());
249 if (All == true)
250 return allCodes;
251 else
252 return codes;
253 }
254
45df0ad2
DK
255 std::vector<string> const lang = _config->FindVector("Acquire::Languages");
256 // the default setting -> "environment, en"
257 if (lang.empty() == true) {
d7cf5923 258 codes = environment;
45df0ad2
DK
259 if (envShort != "en")
260 codes.push_back("en");
d7cf5923 261 allCodes = codes;
3f2d77b5
DK
262 for (std::vector<string>::const_iterator b = builtin.begin();
263 b != builtin.end(); ++b)
264 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
265 allCodes.push_back(*b);
266 if (All == true)
267 return allCodes;
268 else
269 return codes;
45df0ad2
DK
270 }
271
272 // the configs define the order, so add the environment
273 // then needed and ensure the codes are not listed twice.
274 bool noneSeen = false;
275 for (std::vector<string>::const_iterator l = lang.begin();
276 l != lang.end(); l++) {
277 if (*l == "environment") {
d7cf5923
DK
278 for (std::vector<string>::const_iterator e = environment.begin();
279 e != environment.end(); ++e) {
280 if (std::find(allCodes.begin(), allCodes.end(), *e) != allCodes.end())
281 continue;
45df0ad2 282 if (noneSeen == false)
d7cf5923
DK
283 codes.push_back(*e);
284 allCodes.push_back(*e);
45df0ad2
DK
285 }
286 continue;
287 } else if (*l == "none") {
288 noneSeen = true;
289 continue;
d7cf5923 290 } else if (std::find(allCodes.begin(), allCodes.end(), *l) != allCodes.end())
45df0ad2
DK
291 continue;
292
293 if (noneSeen == false)
294 codes.push_back(*l);
295 allCodes.push_back(*l);
296 }
3f2d77b5
DK
297
298 for (std::vector<string>::const_iterator b = builtin.begin();
299 b != builtin.end(); ++b)
300 if (std::find(allCodes.begin(), allCodes.end(), *b) == allCodes.end())
301 allCodes.push_back(*b);
302
45df0ad2
DK
303 if (All == true)
304 return allCodes;
305 else
306 return codes;
307}
308 /*}}}*/
5dd4c8b8
DK
309// getArchitectures - Return Vector of prefered Architectures /*{{{*/
310std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) {
311 using std::string;
312
313 std::vector<string> static archs;
314 if (likely(Cached == true) && archs.empty() == false)
315 return archs;
316
5dd4c8b8 317 archs = _config->FindVector("APT::Architectures");
3152f4aa
DK
318 string const arch = _config->Find("APT::Architecture");
319 if (unlikely(arch.empty() == true))
320 return archs;
321
5dd4c8b8
DK
322 if (archs.empty() == true ||
323 std::find(archs.begin(), archs.end(), arch) == archs.end())
324 archs.push_back(arch);
3152f4aa
DK
325
326 // erase duplicates and empty strings
327 for (std::vector<string>::reverse_iterator a = archs.rbegin();
328 a != archs.rend(); ++a) {
329 if (a->empty() == true || std::find(a + 1, archs.rend(), *a) != archs.rend())
330 archs.erase(a.base()-1);
331 if (a == archs.rend())
332 break;
333 }
334
5dd4c8b8
DK
335 return archs;
336}
337 /*}}}*/
338// checkArchitecture - are we interested in the given Architecture? /*{{{*/
339bool const Configuration::checkArchitecture(std::string const &Arch) {
340 if (Arch == "all")
341 return true;
342 std::vector<std::string> const archs = getArchitectures(true);
343 return (std::find(archs.begin(), archs.end(), Arch) != archs.end());
344}
345 /*}}}*/
03bef784
DK
346// setDefaultConfigurationForCompressors /*{{{*/
347void Configuration::setDefaultConfigurationForCompressors() {
348 // Set default application paths to check for optional compression types
349 _config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
350 _config->CndSet("Dir::Bin::xz", "/usr/bin/xz");
351 _config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
352}
353 /*}}}*/
354// getCompressors - Return Vector of usbale compressors /*{{{*/
355// ---------------------------------------------------------------------
356/* return a vector of compressors used by apt-ftparchive in the
357 multicompress functionality or to detect data.tar files */
358std::vector<APT::Configuration::Compressor>
359const Configuration::getCompressors(bool const Cached) {
360 static std::vector<APT::Configuration::Compressor> compressors;
361 if (compressors.empty() == false) {
362 if (Cached == true)
363 return compressors;
364 else
365 compressors.clear();
366 }
367
368 setDefaultConfigurationForCompressors();
369
370 compressors.push_back(Compressor(".", "", "", "", "", 1));
371 if (_config->Exists("Dir::Bin::gzip") == false || FileExists(_config->FindFile("Dir::Bin::gzip")) == true)
372 compressors.push_back(Compressor("gzip",".gz","gzip","-9n","-d",2));
373 if (_config->Exists("Dir::Bin::bzip2") == false || FileExists(_config->FindFile("Dir::Bin::bzip2")) == true)
374 compressors.push_back(Compressor("bzip2",".bz2","bzip2","-9","-d",3));
375 if (_config->Exists("Dir::Bin::lzma") == false || FileExists(_config->FindFile("Dir::Bin::lzma")) == true)
376 compressors.push_back(Compressor("lzma",".lzma","lzma","-9","-d",4));
377 if (_config->Exists("Dir::Bin::xz") == false || FileExists(_config->FindFile("Dir::Bin::xz")) == true)
378 compressors.push_back(Compressor("xz",".xz","xz","-6","-d",5));
379
380 std::vector<std::string> const comp = _config->FindVector("APT::Compressor");
381 for (std::vector<std::string>::const_iterator c = comp.begin();
382 c != comp.end(); ++c) {
383 if (*c == "." || *c == "gzip" || *c == "bzip2" || *c == "lzma" || *c == "xz")
384 continue;
385 compressors.push_back(Compressor(c->c_str(), std::string(".").append(*c).c_str(), c->c_str(), "-9", "-d", 100));
386 }
387
388 return compressors;
389}
390 /*}}}*/
b0e1a43f
DK
391// getCompressorExtensions - supported data.tar extensions /*{{{*/
392// ---------------------------------------------------------------------
393/* */
394std::vector<std::string> const Configuration::getCompressorExtensions() {
395 std::vector<APT::Configuration::Compressor> const compressors = getCompressors();
396 std::vector<std::string> ext;
397 for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressors.begin();
398 c != compressors.end(); ++c)
399 if (c->Extension.empty() == false && c->Extension != ".")
400 ext.push_back(c->Extension);
401 return ext;
402}
403 /*}}}*/
03bef784
DK
404// Compressor constructor /*{{{*/
405// ---------------------------------------------------------------------
406/* */
407Configuration::Compressor::Compressor(char const *name, char const *extension,
408 char const *binary,
409 char const *compressArg, char const *uncompressArg,
410 unsigned short const cost) {
411 std::string const config = string("APT:Compressor::").append(name).append("::");
412 Name = _config->Find(std::string(config).append("Name"), name);
413 Extension = _config->Find(std::string(config).append("Extension"), extension);
414 Binary = _config->Find(std::string(config).append("Binary"), binary);
415 Cost = _config->FindI(std::string(config).append("Cost"), cost);
416 std::string const compConf = std::string(config).append("CompressArg");
417 if (_config->Exists(compConf) == true)
418 CompressArgs = _config->FindVector(compConf);
419 else if (compressArg != NULL)
420 CompressArgs.push_back(compressArg);
421 std::string const uncompConf = std::string(config).append("UncompressArg");
422 if (_config->Exists(uncompConf) == true)
423 UncompressArgs = _config->FindVector(uncompConf);
424 else if (uncompressArg != NULL)
425 UncompressArgs.push_back(uncompressArg);
426}
427 /*}}}*/
e878aedb 428}