]>
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 if (FileExists(_config
->FindFile("Dir::Bin::xz")) == true) {
41 _config
->Set("Dir::Bin::lzma", _config
->FindFile("Dir::Bin::xz"));
42 _config
->Set("APT::Compressor::lzma::Binary", "xz");
43 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
44 _config
->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");
45 _config
->Set("APT::Compressor::lzma::CompressArg::", "-9");
47 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
48 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--format=lzma");
49 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
52 _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
53 if (_config
->Exists("APT::Compressor::lzma::CompressArg") == false) {
54 _config
->Set("APT::Compressor::lzma::CompressArg::", "--suffix=");
55 _config
->Set("APT::Compressor::lzma::CompressArg::", "-9");
57 if (_config
->Exists("APT::Compressor::lzma::UncompressArg") == false) {
58 _config
->Set("APT::Compressor::lzma::UncompressArg::", "--suffix=");
59 _config
->Set("APT::Compressor::lzma::UncompressArg::", "-d");
64 // getCompressionTypes - Return Vector of usable compressiontypes /*{{{*/
65 // ---------------------------------------------------------------------
66 /* return a vector of compression types in the preferred order. */
67 std::vector
<std::string
>
68 const Configuration::getCompressionTypes(bool const &Cached
) {
69 static std::vector
<std::string
> types
;
70 if (types
.empty() == false) {
77 // setup the defaults for the compressiontypes => method mapping
78 _config
->CndSet("Acquire::CompressionTypes::xz","xz");
79 _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2");
80 _config
->CndSet("Acquire::CompressionTypes::lzma","lzma");
81 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
83 setDefaultConfigurationForCompressors();
84 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
86 // load the order setting into our vector
87 std::vector
<std::string
> const order
= _config
->FindVector("Acquire::CompressionTypes::Order");
88 for (std::vector
<std::string
>::const_iterator o
= order
.begin();
89 o
!= order
.end(); ++o
) {
90 if ((*o
).empty() == true)
92 // ignore types we have no method ready to use
93 std::string
const method
= std::string("Acquire::CompressionTypes::").append(*o
);
94 if (_config
->Exists(method
) == false)
96 // ignore types we have no app ready to use
97 std::string
const app
= _config
->Find(method
);
98 if (std::find_if(compressors
.begin(), compressors
.end(), [&app
](APT::Configuration::Compressor
const &c
) {
100 }) == compressors
.end())
105 // move again over the option tree to add all missing compression types
106 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
108 Types
= Types
->Child
;
110 for (; Types
!= 0; Types
= Types
->Next
) {
111 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
113 // ignore types we already have in the vector
114 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
116 // ignore types we have no app ready to use
117 if (std::find_if(compressors
.begin(), compressors
.end(), [&Types
](APT::Configuration::Compressor
const &c
) {
118 return c
.Name
== Types
->Value
;
119 }) == compressors
.end())
121 types
.push_back(Types
->Tag
);
124 // add the special "uncompressed" type
125 if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end())
127 std::string
const uncompr
= _config
->FindFile("Dir::Bin::uncompressed", "");
128 if (uncompr
.empty() == true || FileExists(uncompr
) == true)
129 types
.push_back("uncompressed");
135 // GetLanguages - Return Vector of Language Codes /*{{{*/
136 // ---------------------------------------------------------------------
137 /* return a vector of language codes in the preferred order.
138 the special word "environment" will be replaced with the long and the short
139 code of the local settings and it will be insured that this will not add
140 duplicates. So in an german local the setting "environment, de_DE, en, de"
141 will result in "de_DE, de, en".
142 The special word "none" is the stopcode for the not-All code vector */
143 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
144 bool const &Cached
, char const ** const Locale
) {
147 // The detection is boring and has a lot of cornercases,
148 // so we cache the results to calculated it only once.
149 std::vector
<string
> static allCodes
;
150 std::vector
<string
> static codes
;
152 // we have something in the cache
153 if (codes
.empty() == false || allCodes
.empty() == false) {
154 if (Cached
== true) {
155 if(All
== true && allCodes
.empty() == false)
165 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
166 // so they will be all included in the Cache.
167 std::vector
<string
> builtin
;
168 DIR *D
= opendir(_config
->FindDir("Dir::State::lists").c_str());
170 builtin
.push_back("none");
171 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
)) {
172 string
const name
= SubstVar(Ent
->d_name
, "%5f", "_");
173 size_t const foundDash
= name
.rfind("-");
174 size_t const foundUnderscore
= name
.rfind("_", foundDash
);
175 if (foundDash
== string::npos
|| foundUnderscore
== string::npos
||
176 foundDash
<= foundUnderscore
||
177 name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation")
179 string
const c
= name
.substr(foundDash
+1);
180 if (unlikely(c
.empty() == true) || c
== "en")
182 // Skip unusual files, like backups or that alike
183 string::const_iterator s
= c
.begin();
184 for (;s
!= c
.end(); ++s
) {
185 if (isalpha(*s
) == 0 && *s
!= '_')
190 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
192 builtin
.push_back(c
);
197 // FIXME: Remove support for the old APT::Acquire::Translation
198 // it was undocumented and so it should be not very widthly used
199 string
const oldAcquire
= _config
->Find("APT::Acquire::Translation","");
200 if (oldAcquire
.empty() == false && oldAcquire
!= "environment") {
201 // TRANSLATORS: the two %s are APT configuration options
202 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
203 "APT::Acquire::Translation", "Acquire::Languages");
204 if (oldAcquire
!= "none")
205 codes
.push_back(oldAcquire
);
206 codes
.push_back("en");
208 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
209 b
!= builtin
.end(); ++b
)
210 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
211 allCodes
.push_back(*b
);
218 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
219 // we extract both, a long and a short code and then we will
220 // check if we actually need both (rare) or if the short is enough
221 string
const envMsg
= string(Locale
== 0 ? ::setlocale(LC_MESSAGES
, NULL
) : *Locale
);
222 size_t const lenShort
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2;
223 size_t const lenLong
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort
+ 3);
225 string
const envLong
= envMsg
.substr(0,lenLong
);
226 string
const envShort
= envLong
.substr(0,lenShort
);
228 // It is very likely we will need the environment codes later,
229 // so let us generate them now from LC_MESSAGES and LANGUAGE
230 std::vector
<string
> environment
;
231 if (envShort
!= "C") {
232 // take care of LC_MESSAGES
233 if (envLong
!= envShort
)
234 environment
.push_back(envLong
);
235 environment
.push_back(envShort
);
236 // take care of LANGUAGE
237 const char *language_env
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
238 string envLang
= Locale
== 0 ? language_env
: *(Locale
+1);
239 if (envLang
.empty() == false) {
240 std::vector
<string
> env
= VectorizeString(envLang
,':');
241 short addedLangs
= 0; // add a maximum of 3 fallbacks from the environment
242 for (std::vector
<string
>::const_iterator e
= env
.begin();
243 e
!= env
.end() && addedLangs
< 3; ++e
) {
244 if (unlikely(e
->empty() == true) || *e
== "en")
246 if (*e
== envLong
|| *e
== envShort
)
248 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
251 environment
.push_back(*e
);
255 // cornercase: LANG=C, so we use only "en" Translation
256 environment
.push_back("en");
259 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages", "environment,en");
260 // the configs define the order, so add the environment
261 // then needed and ensure the codes are not listed twice.
262 bool noneSeen
= false;
263 for (std::vector
<string
>::const_iterator l
= lang
.begin();
264 l
!= lang
.end(); ++l
) {
265 if (*l
== "environment") {
266 for (std::vector
<string
>::const_iterator e
= environment
.begin();
267 e
!= environment
.end(); ++e
) {
268 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end())
270 if (noneSeen
== false)
272 allCodes
.push_back(*e
);
275 } else if (*l
== "none") {
278 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
281 if (noneSeen
== false)
283 allCodes
.push_back(*l
);
286 if (allCodes
.empty() == false) {
287 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
288 b
!= builtin
.end(); ++b
)
289 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
290 allCodes
.push_back(*b
);
293 allCodes
.push_back("none");
302 // checkLanguage - are we interested in the given Language? /*{{{*/
303 bool Configuration::checkLanguage(std::string Lang
, bool const All
) {
304 // the empty Language is always interesting as it is the original
305 if (Lang
.empty() == true)
307 // filenames are encoded, so undo this
308 Lang
= SubstVar(Lang
, "%5f", "_");
309 std::vector
<std::string
> const langs
= getLanguages(All
, true);
310 return (std::find(langs
.begin(), langs
.end(), Lang
) != langs
.end());
313 // getArchitectures - Return Vector of preferred Architectures /*{{{*/
314 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) {
317 std::vector
<string
> static archs
;
318 if (likely(Cached
== true) && archs
.empty() == false)
321 string
const arch
= _config
->Find("APT::Architecture");
322 archs
= _config
->FindVector("APT::Architectures");
324 if (archs
.empty() == true)
325 archs
= _system
->ArchitecturesSupported();
327 if (archs
.empty() == true ||
328 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
329 archs
.insert(archs
.begin(), arch
);
331 // erase duplicates and empty strings
332 for (std::vector
<string
>::reverse_iterator a
= archs
.rbegin();
333 a
!= archs
.rend(); ++a
) {
334 if (a
->empty() == true || std::find(a
+ 1, archs
.rend(), *a
) != archs
.rend())
335 archs
.erase(a
.base()-1);
336 if (a
== archs
.rend())
343 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
344 bool Configuration::checkArchitecture(std::string
const &Arch
) {
347 std::vector
<std::string
> const archs
= getArchitectures(true);
348 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());
351 // getCompressors - Return Vector of usealbe compressors /*{{{*/
352 // ---------------------------------------------------------------------
353 /* return a vector of compressors used by apt-ftparchive in the
354 multicompress functionality or to detect data.tar files */
355 std::vector
<APT::Configuration::Compressor
>
356 const Configuration::getCompressors(bool const Cached
) {
357 static std::vector
<APT::Configuration::Compressor
> compressors
;
358 if (compressors
.empty() == false) {
365 setDefaultConfigurationForCompressors();
367 compressors
.push_back(Compressor(".", "", "", NULL
, NULL
, 1));
368 if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->FindFile("Dir::Bin::gzip")) == true)
369 compressors
.push_back(Compressor("gzip",".gz","gzip","-9n","-d",2));
372 compressors
.push_back(Compressor("gzip",".gz","false", NULL
, NULL
, 2));
374 if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->FindFile("Dir::Bin::xz")) == true)
375 compressors
.push_back(Compressor("xz",".xz","xz","-6","-d",3));
378 compressors
.push_back(Compressor("xz",".xz","false", NULL
, NULL
, 3));
380 if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->FindFile("Dir::Bin::bzip2")) == true)
381 compressors
.push_back(Compressor("bzip2",".bz2","bzip2","-9","-d",4));
384 compressors
.push_back(Compressor("bzip2",".bz2","false", NULL
, NULL
, 4));
386 if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->FindFile("Dir::Bin::lzma")) == true)
387 compressors
.push_back(Compressor("lzma",".lzma","lzma","-9","-d",5));
390 compressors
.push_back(Compressor("lzma",".lzma","false", NULL
, NULL
, 5));
393 std::vector
<std::string
> const comp
= _config
->FindVector("APT::Compressor");
394 for (std::vector
<std::string
>::const_iterator c
= comp
.begin();
395 c
!= comp
.end(); ++c
) {
396 if (c
->empty() || *c
== "." || *c
== "gzip" || *c
== "bzip2" || *c
== "lzma" || *c
== "xz")
398 compressors
.push_back(Compressor(c
->c_str(), std::string(".").append(*c
).c_str(), c
->c_str(), "-9", "-d", 100));
404 // getCompressorExtensions - supported data.tar extensions /*{{{*/
405 // ---------------------------------------------------------------------
407 std::vector
<std::string
> const Configuration::getCompressorExtensions() {
408 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
409 std::vector
<std::string
> ext
;
410 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressors
.begin();
411 c
!= compressors
.end(); ++c
)
412 if (c
->Extension
.empty() == false && c
->Extension
!= ".")
413 ext
.push_back(c
->Extension
);
417 // Compressor constructor /*{{{*/
418 // ---------------------------------------------------------------------
420 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
422 char const *compressArg
, char const *uncompressArg
,
423 unsigned short const cost
) {
424 std::string
const config
= std::string("APT::Compressor::").append(name
).append("::");
425 Name
= _config
->Find(std::string(config
).append("Name"), name
);
426 Extension
= _config
->Find(std::string(config
).append("Extension"), extension
);
427 Binary
= _config
->Find(std::string(config
).append("Binary"), binary
);
428 Cost
= _config
->FindI(std::string(config
).append("Cost"), cost
);
429 std::string
const compConf
= std::string(config
).append("CompressArg");
430 if (_config
->Exists(compConf
) == true)
431 CompressArgs
= _config
->FindVector(compConf
);
432 else if (compressArg
!= NULL
)
433 CompressArgs
.push_back(compressArg
);
434 std::string
const uncompConf
= std::string(config
).append("UncompressArg");
435 if (_config
->Exists(uncompConf
) == true)
436 UncompressArgs
= _config
->FindVector(uncompConf
);
437 else if (uncompressArg
!= NULL
)
438 UncompressArgs
.push_back(uncompressArg
);
441 // getBuildProfiles - return a vector of enabled build profiles /*{{{*/
442 std::vector
<std::string
> const Configuration::getBuildProfiles() {
443 // order is: override value (~= commandline), environment variable, list (~= config file)
444 std::string profiles_env
= getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
445 if (profiles_env
.empty() == false) {
446 profiles_env
= SubstVar(profiles_env
, " ", ",");
447 std::string
const bp
= _config
->Find("APT::Build-Profiles");
448 _config
->Clear("APT::Build-Profiles");
449 if (bp
.empty() == false)
450 _config
->Set("APT::Build-Profiles", bp
);
452 return _config
->FindVector("APT::Build-Profiles", profiles_env
);
454 std::string
const Configuration::getBuildProfilesString() {
455 std::vector
<std::string
> profiles
= getBuildProfiles();
456 if (profiles
.empty() == true)
458 std::vector
<std::string
>::const_iterator p
= profiles
.begin();
459 std::string list
= *p
;
460 for (++p
; p
!= profiles
.end(); ++p
)
461 list
.append(",").append(*p
);