]>
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::gzip", "/bin/gzip");
39 _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
40 _config
->CndSet("Dir::Bin::xz", "/usr/bin/xz");
41 _config
->CndSet("Dir::Bin::lz4", "/usr/bin/lz4");
42 if (FileExists(_config
->Find("Dir::Bin::xz")) == true) {
43 _config
->Set("Dir::Bin::lzma", _config
->Find("Dir::Bin::xz"));
44 _config
->Set("APT::Compressor::lzma::Binary", "xz");
45 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
46 _config
->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
47 _config
->Set("APT::Compressor::lzma::CompressArg::", "-6");
49 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
50 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
51 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
54 _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
55 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
56 _config
->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
57 _config
->Set("APT::Compressor::lzma::CompressArg::", "-6");
59 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
60 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
61 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
64 // setup the defaults for the compressiontypes => method mapping
65 _config
->CndSet("Acquire::CompressionTypes::xz","xz");
66 _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2");
67 _config
->CndSet("Acquire::CompressionTypes::lzma","lzma");
68 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
69 _config
->CndSet("Acquire::CompressionTypes::lz4","lz4");
72 // getCompressionTypes - Return Vector of usable compressiontypes /*{{{*/
73 // ---------------------------------------------------------------------
74 /* return a vector of compression types in the preferred order. */
75 std::vector
<std::string
>
76 const Configuration::getCompressionTypes(bool const &Cached
) {
77 static std::vector
<std::string
> types
;
78 if (types
.empty() == false) {
85 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
87 // load the order setting into our vector
88 std::vector
<std::string
> const order
= _config
->FindVector("Acquire::CompressionTypes::Order");
89 for (std::vector
<std::string
>::const_iterator o
= order
.begin();
90 o
!= order
.end(); ++o
) {
91 if ((*o
).empty() == true)
93 // ignore types we have no method ready to use
94 std::string
const method
= std::string("Acquire::CompressionTypes::").append(*o
);
95 if (_config
->Exists(method
) == false)
97 // ignore types we have no app ready to use
98 std::string
const app
= _config
->Find(method
);
99 if (std::find_if(compressors
.begin(), compressors
.end(), [&app
](APT::Configuration::Compressor
const &c
) {
100 return c
.Name
== app
;
101 }) == compressors
.end())
106 // move again over the option tree to add all missing compression types
107 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
109 Types
= Types
->Child
;
111 for (; Types
!= 0; Types
= Types
->Next
) {
112 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
114 // ignore types we already have in the vector
115 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
117 // ignore types we have no app ready to use
118 if (std::find_if(compressors
.begin(), compressors
.end(), [&Types
](APT::Configuration::Compressor
const &c
) {
119 return c
.Name
== Types
->Value
;
120 }) == compressors
.end())
122 types
.push_back(Types
->Tag
);
125 // add the special "uncompressed" type
126 if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end())
128 std::string
const uncompr
= _config
->Find("Dir::Bin::uncompressed", "");
129 if (uncompr
.empty() == true || FileExists(uncompr
) == true)
130 types
.push_back("uncompressed");
136 // GetLanguages - Return Vector of Language Codes /*{{{*/
137 // ---------------------------------------------------------------------
138 /* return a vector of language codes in the preferred order.
139 the special word "environment" will be replaced with the long and the short
140 code of the local settings and it will be insured that this will not add
141 duplicates. So in an german local the setting "environment, de_DE, en, de"
142 will result in "de_DE, de, en".
143 The special word "none" is the stopcode for the not-All code vector */
144 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
145 bool const &Cached
, char const ** const Locale
) {
148 // The detection is boring and has a lot of cornercases,
149 // so we cache the results to calculated it only once.
150 std::vector
<string
> static allCodes
;
151 std::vector
<string
> static codes
;
153 // we have something in the cache
154 if (codes
.empty() == false || allCodes
.empty() == false) {
155 if (Cached
== true) {
156 if(All
== true && allCodes
.empty() == false)
166 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
167 // so they will be all included in the Cache.
168 std::vector
<string
> builtin
;
169 DIR *D
= opendir(_config
->FindDir("Dir::State::lists").c_str());
171 builtin
.push_back("none");
172 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
)) {
173 string
const name
= SubstVar(Ent
->d_name
, "%5f", "_");
174 size_t const foundDash
= name
.rfind("-");
175 size_t const foundUnderscore
= name
.rfind("_", foundDash
);
176 if (foundDash
== string::npos
|| foundUnderscore
== string::npos
||
177 foundDash
<= foundUnderscore
||
178 name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation")
180 string
const c
= name
.substr(foundDash
+1);
181 if (unlikely(c
.empty() == true) || c
== "en")
183 // Skip unusual files, like backups or that alike
184 string::const_iterator s
= c
.begin();
185 for (;s
!= c
.end(); ++s
) {
186 if (isalpha(*s
) == 0 && *s
!= '_')
191 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
193 builtin
.push_back(c
);
198 // FIXME: Remove support for the old APT::Acquire::Translation
199 // it was undocumented and so it should be not very widthly used
200 string
const oldAcquire
= _config
->Find("APT::Acquire::Translation","");
201 if (oldAcquire
.empty() == false && oldAcquire
!= "environment") {
202 // TRANSLATORS: the two %s are APT configuration options
203 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
204 "APT::Acquire::Translation", "Acquire::Languages");
205 if (oldAcquire
!= "none")
206 codes
.push_back(oldAcquire
);
207 codes
.push_back("en");
209 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
210 b
!= builtin
.end(); ++b
)
211 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
212 allCodes
.push_back(*b
);
219 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
220 // we extract both, a long and a short code and then we will
221 // check if we actually need both (rare) or if the short is enough
222 string
const envMsg
= string(Locale
== 0 ? ::setlocale(LC_MESSAGES
, NULL
) : *Locale
);
223 size_t const lenShort
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2;
224 size_t const lenLong
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort
+ 3);
226 string
const envLong
= envMsg
.substr(0,lenLong
);
227 string
const envShort
= envLong
.substr(0,lenShort
);
229 // It is very likely we will need the environment codes later,
230 // so let us generate them now from LC_MESSAGES and LANGUAGE
231 std::vector
<string
> environment
;
232 if (envShort
!= "C") {
233 // take care of LC_MESSAGES
234 if (envLong
!= envShort
)
235 environment
.push_back(envLong
);
236 environment
.push_back(envShort
);
237 // take care of LANGUAGE
238 const char *language_env
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
239 string envLang
= Locale
== 0 ? language_env
: *(Locale
+1);
240 if (envLang
.empty() == false) {
241 std::vector
<string
> env
= VectorizeString(envLang
,':');
242 short addedLangs
= 0; // add a maximum of 3 fallbacks from the environment
243 for (std::vector
<string
>::const_iterator e
= env
.begin();
244 e
!= env
.end() && addedLangs
< 3; ++e
) {
245 if (unlikely(e
->empty() == true) || *e
== "en")
247 if (*e
== envLong
|| *e
== envShort
)
249 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
252 environment
.push_back(*e
);
256 // cornercase: LANG=C, so we use only "en" Translation
257 environment
.push_back("en");
260 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages", "environment,en");
261 // the configs define the order, so add the environment
262 // then needed and ensure the codes are not listed twice.
263 bool noneSeen
= false;
264 for (std::vector
<string
>::const_iterator l
= lang
.begin();
265 l
!= lang
.end(); ++l
) {
266 if (*l
== "environment") {
267 for (std::vector
<string
>::const_iterator e
= environment
.begin();
268 e
!= environment
.end(); ++e
) {
269 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end())
271 if (noneSeen
== false)
273 allCodes
.push_back(*e
);
276 } else if (*l
== "none") {
279 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
282 if (noneSeen
== false)
284 allCodes
.push_back(*l
);
287 if (allCodes
.empty() == false) {
288 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
289 b
!= builtin
.end(); ++b
)
290 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
291 allCodes
.push_back(*b
);
294 allCodes
.push_back("none");
303 // checkLanguage - are we interested in the given Language? /*{{{*/
304 bool Configuration::checkLanguage(std::string Lang
, bool const All
) {
305 // the empty Language is always interesting as it is the original
306 if (Lang
.empty() == true)
308 // filenames are encoded, so undo this
309 Lang
= SubstVar(Lang
, "%5f", "_");
310 std::vector
<std::string
> const langs
= getLanguages(All
, true);
311 return (std::find(langs
.begin(), langs
.end(), Lang
) != langs
.end());
314 // getArchitectures - Return Vector of preferred Architectures /*{{{*/
315 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) {
318 std::vector
<string
> static archs
;
319 if (likely(Cached
== true) && archs
.empty() == false)
322 string
const arch
= _config
->Find("APT::Architecture");
323 archs
= _config
->FindVector("APT::Architectures");
325 if (archs
.empty() == true)
326 archs
= _system
->ArchitecturesSupported();
328 if (archs
.empty() == true ||
329 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
330 archs
.insert(archs
.begin(), arch
);
332 // erase duplicates and empty strings
333 for (std::vector
<string
>::reverse_iterator a
= archs
.rbegin();
334 a
!= archs
.rend(); ++a
) {
335 if (a
->empty() == true || std::find(a
+ 1, archs
.rend(), *a
) != archs
.rend())
336 archs
.erase(a
.base()-1);
337 if (a
== archs
.rend())
344 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
345 bool Configuration::checkArchitecture(std::string
const &Arch
) {
348 std::vector
<std::string
> const archs
= getArchitectures(true);
349 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());
352 // getCompressors - Return Vector of usealbe compressors /*{{{*/
353 // ---------------------------------------------------------------------
354 /* return a vector of compressors used by apt-ftparchive in the
355 multicompress functionality or to detect data.tar files */
356 std::vector
<APT::Configuration::Compressor
>
357 const Configuration::getCompressors(bool const Cached
) {
358 static std::vector
<APT::Configuration::Compressor
> compressors
;
359 if (compressors
.empty() == false) {
366 setDefaultConfigurationForCompressors();
368 compressors
.push_back(Compressor(".", "", "", NULL
, NULL
, 0));
369 if (_config
->Exists("Dir::Bin::lz4") == false || FileExists(_config
->Find("Dir::Bin::lz4")) == true)
370 compressors
.push_back(Compressor("lz4",".lz4","lz4","-1","-d",50));
373 compressors
.push_back(Compressor("lz4",".lz4","false", NULL
, NULL
, 50));
375 if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->Find("Dir::Bin::gzip")) == true)
376 compressors
.push_back(Compressor("gzip",".gz","gzip","-6n","-d",100));
379 compressors
.push_back(Compressor("gzip",".gz","false", NULL
, NULL
, 100));
381 if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->Find("Dir::Bin::xz")) == true)
382 compressors
.push_back(Compressor("xz",".xz","xz","-6","-d",200));
385 compressors
.push_back(Compressor("xz",".xz","false", NULL
, NULL
, 200));
387 if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->Find("Dir::Bin::bzip2")) == true)
388 compressors
.push_back(Compressor("bzip2",".bz2","bzip2","-6","-d",300));
391 compressors
.push_back(Compressor("bzip2",".bz2","false", NULL
, NULL
, 300));
393 if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->Find("Dir::Bin::lzma")) == true)
394 compressors
.push_back(Compressor("lzma",".lzma","lzma","-6","-d",400));
397 compressors
.push_back(Compressor("lzma",".lzma","false", NULL
, NULL
, 400));
400 std::vector
<std::string
> const comp
= _config
->FindVector("APT::Compressor", "", true);
401 for (auto const &c
: comp
)
403 if (c
.empty() || std::any_of(compressors
.begin(), compressors
.end(), [&c
](Compressor
const &ac
) { return ac
.Name
== c
; }))
405 compressors
.push_back(Compressor(c
.c_str(), std::string(".").append(c
).c_str(), c
.c_str(), nullptr, nullptr, 1000));
411 // getCompressorExtensions - supported data.tar extensions /*{{{*/
412 // ---------------------------------------------------------------------
414 std::vector
<std::string
> const Configuration::getCompressorExtensions() {
415 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
416 std::vector
<std::string
> ext
;
417 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressors
.begin();
418 c
!= compressors
.end(); ++c
)
419 if (c
->Extension
.empty() == false && c
->Extension
!= ".")
420 ext
.push_back(c
->Extension
);
424 // Compressor constructor /*{{{*/
425 // ---------------------------------------------------------------------
427 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
429 char const *compressArg
, char const *uncompressArg
,
430 unsigned short const cost
) {
431 std::string
const config
= std::string("APT::Compressor::").append(name
).append("::");
432 Name
= _config
->Find(std::string(config
).append("Name"), name
);
433 Extension
= _config
->Find(std::string(config
).append("Extension"), extension
);
434 Binary
= _config
->Find(std::string(config
).append("Binary"), binary
);
435 Cost
= _config
->FindI(std::string(config
).append("Cost"), cost
);
436 std::string
const compConf
= std::string(config
).append("CompressArg");
437 if (_config
->Exists(compConf
) == true)
438 CompressArgs
= _config
->FindVector(compConf
);
439 else if (compressArg
!= NULL
)
440 CompressArgs
.push_back(compressArg
);
441 std::string
const uncompConf
= std::string(config
).append("UncompressArg");
442 if (_config
->Exists(uncompConf
) == true)
443 UncompressArgs
= _config
->FindVector(uncompConf
);
444 else if (uncompressArg
!= NULL
)
445 UncompressArgs
.push_back(uncompressArg
);
448 // getBuildProfiles - return a vector of enabled build profiles /*{{{*/
449 std::vector
<std::string
> const Configuration::getBuildProfiles() {
450 // order is: override value (~= commandline), environment variable, list (~= config file)
451 std::string profiles_env
= getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
452 if (profiles_env
.empty() == false) {
453 profiles_env
= SubstVar(profiles_env
, " ", ",");
454 std::string
const bp
= _config
->Find("APT::Build-Profiles");
455 _config
->Clear("APT::Build-Profiles");
456 if (bp
.empty() == false)
457 _config
->Set("APT::Build-Profiles", bp
);
459 return _config
->FindVector("APT::Build-Profiles", profiles_env
);
461 std::string
const Configuration::getBuildProfilesString() {
462 std::vector
<std::string
> profiles
= getBuildProfiles();
463 if (profiles
.empty() == true)
465 std::vector
<std::string
>::const_iterator p
= profiles
.begin();
466 std::string list
= *p
;
467 for (++p
; p
!= profiles
.end(); ++p
)
468 list
.append(",").append(*p
);