]>
git.saurik.com Git - apt.git/blob - apt-pkg/aptconfiguration.cc
1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
5 Provide access methods to various configuration settings,
6 setup defaults and returns validate settings.
8 ##################################################################### */
10 // Include Files /*{{{*/
13 #include <apt-pkg/aptconfiguration.h>
14 #include <apt-pkg/configuration.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/fileutl.h>
17 #include <apt-pkg/macros.h>
18 #include <apt-pkg/strutl.h>
19 #include <apt-pkg/pkgsystem.h>
35 // setDefaultConfigurationForCompressors /*{{{*/
36 static void setDefaultConfigurationForCompressors() {
37 // Set default application paths to check for optional compression types
38 _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
39 _config
->CndSet("Dir::Bin::xz", "/usr/bin/xz");
40 _config
->CndSet("Dir::Bin::lz4", "/usr/bin/lz4");
41 if (FileExists(_config
->FindFile("Dir::Bin::xz")) == true) {
42 _config
->Set("Dir::Bin::lzma", _config
->FindFile("Dir::Bin::xz"));
43 _config
->Set("APT::Compressor::lzma::Binary", "xz");
44 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
45 _config
->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
46 _config
->Set("APT::Compressor::lzma::CompressArg::", "-6");
48 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
49 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
50 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
53 _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
54 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
55 _config
->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
56 _config
->Set("APT::Compressor::lzma::CompressArg::", "-6");
58 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
59 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
60 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
65 // getCompressionTypes - Return Vector of usable compressiontypes /*{{{*/
66 // ---------------------------------------------------------------------
67 /* return a vector of compression types in the preferred order. */
68 std::vector
<std::string
>
69 const Configuration::getCompressionTypes(bool const &Cached
) {
70 static std::vector
<std::string
> types
;
71 if (types
.empty() == false) {
78 // setup the defaults for the compressiontypes => method mapping
79 _config
->CndSet("Acquire::CompressionTypes::xz","xz");
80 _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2");
81 _config
->CndSet("Acquire::CompressionTypes::lzma","lzma");
82 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
83 _config
->CndSet("Acquire::CompressionTypes::lz4","lz4");
85 setDefaultConfigurationForCompressors();
86 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
88 // load the order setting into our vector
89 std::vector
<std::string
> const order
= _config
->FindVector("Acquire::CompressionTypes::Order");
90 for (std::vector
<std::string
>::const_iterator o
= order
.begin();
91 o
!= order
.end(); ++o
) {
92 if ((*o
).empty() == true)
94 // ignore types we have no method ready to use
95 std::string
const method
= std::string("Acquire::CompressionTypes::").append(*o
);
96 if (_config
->Exists(method
) == false)
98 // ignore types we have no app ready to use
99 std::string
const app
= _config
->Find(method
);
100 if (std::find_if(compressors
.begin(), compressors
.end(), [&app
](APT::Configuration::Compressor
const &c
) {
101 return c
.Name
== app
;
102 }) == compressors
.end())
107 // move again over the option tree to add all missing compression types
108 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
110 Types
= Types
->Child
;
112 for (; Types
!= 0; Types
= Types
->Next
) {
113 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
115 // ignore types we already have in the vector
116 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
118 // ignore types we have no app ready to use
119 if (std::find_if(compressors
.begin(), compressors
.end(), [&Types
](APT::Configuration::Compressor
const &c
) {
120 return c
.Name
== Types
->Value
;
121 }) == compressors
.end())
123 types
.push_back(Types
->Tag
);
126 // add the special "uncompressed" type
127 if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end())
129 std::string
const uncompr
= _config
->FindFile("Dir::Bin::uncompressed", "");
130 if (uncompr
.empty() == true || FileExists(uncompr
) == true)
131 types
.push_back("uncompressed");
137 // GetLanguages - Return Vector of Language Codes /*{{{*/
138 // ---------------------------------------------------------------------
139 /* return a vector of language codes in the preferred order.
140 the special word "environment" will be replaced with the long and the short
141 code of the local settings and it will be insured that this will not add
142 duplicates. So in an german local the setting "environment, de_DE, en, de"
143 will result in "de_DE, de, en".
144 The special word "none" is the stopcode for the not-All code vector */
145 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
146 bool const &Cached
, char const ** const Locale
) {
149 // The detection is boring and has a lot of cornercases,
150 // so we cache the results to calculated it only once.
151 std::vector
<string
> static allCodes
;
152 std::vector
<string
> static codes
;
154 // we have something in the cache
155 if (codes
.empty() == false || allCodes
.empty() == false) {
156 if (Cached
== true) {
157 if(All
== true && allCodes
.empty() == false)
167 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
168 // so they will be all included in the Cache.
169 std::vector
<string
> builtin
;
170 DIR *D
= opendir(_config
->FindDir("Dir::State::lists").c_str());
172 builtin
.push_back("none");
173 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
)) {
174 string
const name
= SubstVar(Ent
->d_name
, "%5f", "_");
175 size_t const foundDash
= name
.rfind("-");
176 size_t const foundUnderscore
= name
.rfind("_", foundDash
);
177 if (foundDash
== string::npos
|| foundUnderscore
== string::npos
||
178 foundDash
<= foundUnderscore
||
179 name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation")
181 string
const c
= name
.substr(foundDash
+1);
182 if (unlikely(c
.empty() == true) || c
== "en")
184 // Skip unusual files, like backups or that alike
185 string::const_iterator s
= c
.begin();
186 for (;s
!= c
.end(); ++s
) {
187 if (isalpha(*s
) == 0 && *s
!= '_')
192 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
194 builtin
.push_back(c
);
199 // FIXME: Remove support for the old APT::Acquire::Translation
200 // it was undocumented and so it should be not very widthly used
201 string
const oldAcquire
= _config
->Find("APT::Acquire::Translation","");
202 if (oldAcquire
.empty() == false && oldAcquire
!= "environment") {
203 // TRANSLATORS: the two %s are APT configuration options
204 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
205 "APT::Acquire::Translation", "Acquire::Languages");
206 if (oldAcquire
!= "none")
207 codes
.push_back(oldAcquire
);
208 codes
.push_back("en");
210 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
211 b
!= builtin
.end(); ++b
)
212 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
213 allCodes
.push_back(*b
);
220 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
221 // we extract both, a long and a short code and then we will
222 // check if we actually need both (rare) or if the short is enough
223 string
const envMsg
= string(Locale
== 0 ? ::setlocale(LC_MESSAGES
, NULL
) : *Locale
);
224 size_t const lenShort
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2;
225 size_t const lenLong
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort
+ 3);
227 string
const envLong
= envMsg
.substr(0,lenLong
);
228 string
const envShort
= envLong
.substr(0,lenShort
);
230 // It is very likely we will need the environment codes later,
231 // so let us generate them now from LC_MESSAGES and LANGUAGE
232 std::vector
<string
> environment
;
233 if (envShort
!= "C") {
234 // take care of LC_MESSAGES
235 if (envLong
!= envShort
)
236 environment
.push_back(envLong
);
237 environment
.push_back(envShort
);
238 // take care of LANGUAGE
239 const char *language_env
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
240 string envLang
= Locale
== 0 ? language_env
: *(Locale
+1);
241 if (envLang
.empty() == false) {
242 std::vector
<string
> env
= VectorizeString(envLang
,':');
243 short addedLangs
= 0; // add a maximum of 3 fallbacks from the environment
244 for (std::vector
<string
>::const_iterator e
= env
.begin();
245 e
!= env
.end() && addedLangs
< 3; ++e
) {
246 if (unlikely(e
->empty() == true) || *e
== "en")
248 if (*e
== envLong
|| *e
== envShort
)
250 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
253 environment
.push_back(*e
);
257 // cornercase: LANG=C, so we use only "en" Translation
258 environment
.push_back("en");
261 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages", "environment,en");
262 // the configs define the order, so add the environment
263 // then needed and ensure the codes are not listed twice.
264 bool noneSeen
= false;
265 for (std::vector
<string
>::const_iterator l
= lang
.begin();
266 l
!= lang
.end(); ++l
) {
267 if (*l
== "environment") {
268 for (std::vector
<string
>::const_iterator e
= environment
.begin();
269 e
!= environment
.end(); ++e
) {
270 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end())
272 if (noneSeen
== false)
274 allCodes
.push_back(*e
);
277 } else if (*l
== "none") {
280 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
283 if (noneSeen
== false)
285 allCodes
.push_back(*l
);
288 if (allCodes
.empty() == false) {
289 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
290 b
!= builtin
.end(); ++b
)
291 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
292 allCodes
.push_back(*b
);
295 allCodes
.push_back("none");
304 // checkLanguage - are we interested in the given Language? /*{{{*/
305 bool Configuration::checkLanguage(std::string Lang
, bool const All
) {
306 // the empty Language is always interesting as it is the original
307 if (Lang
.empty() == true)
309 // filenames are encoded, so undo this
310 Lang
= SubstVar(Lang
, "%5f", "_");
311 std::vector
<std::string
> const langs
= getLanguages(All
, true);
312 return (std::find(langs
.begin(), langs
.end(), Lang
) != langs
.end());
315 // getArchitectures - Return Vector of preferred Architectures /*{{{*/
316 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) {
319 std::vector
<string
> static archs
;
320 if (likely(Cached
== true) && archs
.empty() == false)
323 string
const arch
= _config
->Find("APT::Architecture");
324 archs
= _config
->FindVector("APT::Architectures");
326 if (archs
.empty() == true)
327 archs
= _system
->ArchitecturesSupported();
329 if (archs
.empty() == true ||
330 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
331 archs
.insert(archs
.begin(), arch
);
333 // erase duplicates and empty strings
334 for (std::vector
<string
>::reverse_iterator a
= archs
.rbegin();
335 a
!= archs
.rend(); ++a
) {
336 if (a
->empty() == true || std::find(a
+ 1, archs
.rend(), *a
) != archs
.rend())
337 archs
.erase(a
.base()-1);
338 if (a
== archs
.rend())
345 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
346 bool Configuration::checkArchitecture(std::string
const &Arch
) {
349 std::vector
<std::string
> const archs
= getArchitectures(true);
350 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());
353 // getCompressors - Return Vector of usealbe compressors /*{{{*/
354 // ---------------------------------------------------------------------
355 /* return a vector of compressors used by apt-ftparchive in the
356 multicompress functionality or to detect data.tar files */
357 std::vector
<APT::Configuration::Compressor
>
358 const Configuration::getCompressors(bool const Cached
) {
359 static std::vector
<APT::Configuration::Compressor
> compressors
;
360 if (compressors
.empty() == false) {
367 setDefaultConfigurationForCompressors();
369 compressors
.push_back(Compressor(".", "", "", NULL
, NULL
, 0));
370 if (_config
->Exists("Dir::Bin::lz4") == false || FileExists(_config
->FindFile("Dir::Bin::lz4")) == true)
371 compressors
.push_back(Compressor("lz4",".lz4","lz4","-1","-d",50));
374 compressors
.push_back(Compressor("lz4",".lz4","false", NULL
, NULL
, 50));
376 if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->FindFile("Dir::Bin::gzip")) == true)
377 compressors
.push_back(Compressor("gzip",".gz","gzip","-6n","-d",100));
380 compressors
.push_back(Compressor("gzip",".gz","false", NULL
, NULL
, 100));
382 if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->FindFile("Dir::Bin::xz")) == true)
383 compressors
.push_back(Compressor("xz",".xz","xz","-6","-d",200));
386 compressors
.push_back(Compressor("xz",".xz","false", NULL
, NULL
, 200));
388 if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->FindFile("Dir::Bin::bzip2")) == true)
389 compressors
.push_back(Compressor("bzip2",".bz2","bzip2","-6","-d",300));
392 compressors
.push_back(Compressor("bzip2",".bz2","false", NULL
, NULL
, 300));
394 if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->FindFile("Dir::Bin::lzma")) == true)
395 compressors
.push_back(Compressor("lzma",".lzma","lzma","-6","-d",400));
398 compressors
.push_back(Compressor("lzma",".lzma","false", NULL
, NULL
, 400));
401 std::vector
<std::string
> const comp
= _config
->FindVector("APT::Compressor");
402 for (std::vector
<std::string
>::const_iterator c
= comp
.begin();
403 c
!= comp
.end(); ++c
) {
404 if (c
->empty() || *c
== "." || *c
== "gzip" || *c
== "bzip2" || *c
== "lzma" || *c
== "xz")
406 compressors
.push_back(Compressor(c
->c_str(), std::string(".").append(*c
).c_str(), c
->c_str(), "-9", "-d", 100));
412 // getCompressorExtensions - supported data.tar extensions /*{{{*/
413 // ---------------------------------------------------------------------
415 std::vector
<std::string
> const Configuration::getCompressorExtensions() {
416 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
417 std::vector
<std::string
> ext
;
418 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressors
.begin();
419 c
!= compressors
.end(); ++c
)
420 if (c
->Extension
.empty() == false && c
->Extension
!= ".")
421 ext
.push_back(c
->Extension
);
425 // Compressor constructor /*{{{*/
426 // ---------------------------------------------------------------------
428 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
430 char const *compressArg
, char const *uncompressArg
,
431 unsigned short const cost
) {
432 std::string
const config
= std::string("APT::Compressor::").append(name
).append("::");
433 Name
= _config
->Find(std::string(config
).append("Name"), name
);
434 Extension
= _config
->Find(std::string(config
).append("Extension"), extension
);
435 Binary
= _config
->Find(std::string(config
).append("Binary"), binary
);
436 Cost
= _config
->FindI(std::string(config
).append("Cost"), cost
);
437 std::string
const compConf
= std::string(config
).append("CompressArg");
438 if (_config
->Exists(compConf
) == true)
439 CompressArgs
= _config
->FindVector(compConf
);
440 else if (compressArg
!= NULL
)
441 CompressArgs
.push_back(compressArg
);
442 std::string
const uncompConf
= std::string(config
).append("UncompressArg");
443 if (_config
->Exists(uncompConf
) == true)
444 UncompressArgs
= _config
->FindVector(uncompConf
);
445 else if (uncompressArg
!= NULL
)
446 UncompressArgs
.push_back(uncompressArg
);
449 // getBuildProfiles - return a vector of enabled build profiles /*{{{*/
450 std::vector
<std::string
> const Configuration::getBuildProfiles() {
451 // order is: override value (~= commandline), environment variable, list (~= config file)
452 std::string profiles_env
= getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
453 if (profiles_env
.empty() == false) {
454 profiles_env
= SubstVar(profiles_env
, " ", ",");
455 std::string
const bp
= _config
->Find("APT::Build-Profiles");
456 _config
->Clear("APT::Build-Profiles");
457 if (bp
.empty() == false)
458 _config
->Set("APT::Build-Profiles", bp
);
460 return _config
->FindVector("APT::Build-Profiles", profiles_env
);
462 std::string
const Configuration::getBuildProfilesString() {
463 std::vector
<std::string
> profiles
= getBuildProfiles();
464 if (profiles
.empty() == true)
466 std::vector
<std::string
>::const_iterator p
= profiles
.begin();
467 std::string list
= *p
;
468 for (++p
; p
!= profiles
.end(); ++p
)
469 list
.append(",").append(*p
);