]>
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 std::vector
<std::string
> CompressorsDone
;
369 # define APT_ADD_COMPRESSOR(NAME, EXT, BINARY, ARG, DEARG, COST) \
370 { CompressorsDone.push_back(NAME); compressors.emplace_back(NAME, EXT, BINARY, ARG, DEARG, COST); }
371 APT_ADD_COMPRESSOR(".", "", "", nullptr, nullptr, 0)
372 if (_config
->Exists("Dir::Bin::lz4") == false || FileExists(_config
->Find("Dir::Bin::lz4")) == true)
373 APT_ADD_COMPRESSOR("lz4",".lz4","lz4","-1","-d",50)
376 APT_ADD_COMPRESSOR("lz4",".lz4","false", nullptr, nullptr, 50)
378 if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->Find("Dir::Bin::gzip")) == true)
379 APT_ADD_COMPRESSOR("gzip",".gz","gzip","-6n","-d",100)
382 APT_ADD_COMPRESSOR("gzip",".gz","false", nullptr, nullptr, 100)
384 if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->Find("Dir::Bin::xz")) == true)
385 APT_ADD_COMPRESSOR("xz",".xz","xz","-6","-d",200)
388 APT_ADD_COMPRESSOR("xz",".xz","false", nullptr, nullptr, 200)
390 if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->Find("Dir::Bin::bzip2")) == true)
391 APT_ADD_COMPRESSOR("bzip2",".bz2","bzip2","-6","-d",300)
394 APT_ADD_COMPRESSOR("bzip2",".bz2","false", nullptr, nullptr, 300)
396 if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->Find("Dir::Bin::lzma")) == true)
397 APT_ADD_COMPRESSOR("lzma",".lzma","lzma","-6","-d",400)
400 APT_ADD_COMPRESSOR("lzma",".lzma","false", nullptr, nullptr, 400)
403 std::vector
<std::string
> const comp
= _config
->FindVector("APT::Compressor", "", true);
404 for (auto const &c
: comp
)
406 if (c
.empty() || std::find(CompressorsDone
.begin(), CompressorsDone
.end(), c
) != CompressorsDone
.end())
408 compressors
.push_back(Compressor(c
.c_str(), std::string(".").append(c
).c_str(), c
.c_str(), nullptr, nullptr, 1000));
414 // getCompressorExtensions - supported data.tar extensions /*{{{*/
415 // ---------------------------------------------------------------------
417 std::vector
<std::string
> const Configuration::getCompressorExtensions() {
418 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
419 std::vector
<std::string
> ext
;
420 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressors
.begin();
421 c
!= compressors
.end(); ++c
)
422 if (c
->Extension
.empty() == false && c
->Extension
!= ".")
423 ext
.push_back(c
->Extension
);
427 // Compressor constructor /*{{{*/
428 // ---------------------------------------------------------------------
430 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
432 char const *compressArg
, char const *uncompressArg
,
433 unsigned short const cost
) {
434 std::string
const config
= std::string("APT::Compressor::").append(name
).append("::");
435 Name
= _config
->Find(std::string(config
).append("Name"), name
);
436 Extension
= _config
->Find(std::string(config
).append("Extension"), extension
);
437 Binary
= _config
->Find(std::string(config
).append("Binary"), binary
);
438 Cost
= _config
->FindI(std::string(config
).append("Cost"), cost
);
439 std::string
const compConf
= std::string(config
).append("CompressArg");
440 if (_config
->Exists(compConf
) == true)
441 CompressArgs
= _config
->FindVector(compConf
);
442 else if (compressArg
!= NULL
)
443 CompressArgs
.push_back(compressArg
);
444 std::string
const uncompConf
= std::string(config
).append("UncompressArg");
445 if (_config
->Exists(uncompConf
) == true)
446 UncompressArgs
= _config
->FindVector(uncompConf
);
447 else if (uncompressArg
!= NULL
)
448 UncompressArgs
.push_back(uncompressArg
);
451 // getBuildProfiles - return a vector of enabled build profiles /*{{{*/
452 std::vector
<std::string
> const Configuration::getBuildProfiles() {
453 // order is: override value (~= commandline), environment variable, list (~= config file)
454 std::string profiles_env
= getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
455 if (profiles_env
.empty() == false) {
456 profiles_env
= SubstVar(profiles_env
, " ", ",");
457 std::string
const bp
= _config
->Find("APT::Build-Profiles");
458 _config
->Clear("APT::Build-Profiles");
459 if (bp
.empty() == false)
460 _config
->Set("APT::Build-Profiles", bp
);
462 return _config
->FindVector("APT::Build-Profiles", profiles_env
);
464 std::string
const Configuration::getBuildProfilesString() {
465 std::vector
<std::string
> profiles
= getBuildProfiles();
466 if (profiles
.empty() == true)
468 std::vector
<std::string
>::const_iterator p
= profiles
.begin();
469 std::string list
= *p
;
470 for (++p
; p
!= profiles
.end(); ++p
)
471 list
.append(",").append(*p
);