]>
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 /*{{{*/
11 #include <apt-pkg/aptconfiguration.h>
12 #include <apt-pkg/configuration.h>
13 #include <apt-pkg/error.h>
14 #include <apt-pkg/fileutl.h>
15 #include <apt-pkg/macros.h>
16 #include <apt-pkg/strutl.h>
18 #include <sys/types.h>
26 // getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/
27 // ---------------------------------------------------------------------
28 /* return a vector of compression types in the prefered order. */
29 std::vector
<std::string
>
30 const Configuration::getCompressionTypes(bool const &Cached
) {
31 static std::vector
<std::string
> types
;
32 if (types
.empty() == false) {
39 // setup the defaults for the compressiontypes => method mapping
40 _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2");
41 _config
->CndSet("Acquire::CompressionTypes::xz","xz");
42 _config
->CndSet("Acquire::CompressionTypes::lzma","lzma");
43 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
45 setDefaultConfigurationForCompressors();
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
);
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)
58 // ignore types we have no method ready to use
59 if (_config
->Exists(string("Acquire::CompressionTypes::").append(*o
)) == false)
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)
71 // move again over the option tree to add all missing compression types
72 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
76 for (; Types
!= 0; Types
= Types
->Next
) {
77 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
79 // ignore types we already have in the vector
80 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
82 // ignore types we have no app ready to use
83 string
const appsetting
= string("Dir::Bin::").append(Types
->Value
);
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)
89 types
.push_back(Types
->Tag
);
92 // add the special "uncompressed" type
93 if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end())
95 string
const uncompr
= _config
->FindFile("Dir::Bin::uncompressed", "");
96 if (uncompr
.empty() == true || FileExists(uncompr
) == true)
97 types
.push_back("uncompressed");
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 */
111 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
112 bool const &Cached
, char const ** const Locale
) {
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
;
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)
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());
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")
147 string
const c
= name
.substr(foundDash
+1);
148 if (unlikely(c
.empty() == true) || c
== "en")
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)
158 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
160 builtin
.push_back(c
);
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") {
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");
172 if (oldAcquire
!= "none")
173 codes
.push_back(oldAcquire
);
174 codes
.push_back("en");
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
);
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);
193 string
const envLong
= envMsg
.substr(0,lenLong
);
194 string
const envShort
= envLong
.substr(0,lenShort
);
196 // It is very likely we will need the environment codes later,
197 // so let us generate them now from LC_MESSAGES and LANGUAGE
198 std::vector
<string
> environment
;
199 if (envShort
!= "C") {
200 // take care of LC_MESSAGES
201 if (envLong
!= envShort
)
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")
214 if (*e
== envLong
|| *e
== envShort
)
216 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
219 environment
.push_back(*e
);
223 environment
.push_back("en");
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") {
232 } else if (forceLang
!= "none")
233 codes
.push_back(forceLang
);
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
);
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());
255 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages");
256 // the default setting -> "environment, en"
257 if (lang
.empty() == true) {
259 if (envShort
!= "en")
260 codes
.push_back("en");
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
);
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") {
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())
282 if (noneSeen
== false)
284 allCodes
.push_back(*e
);
287 } else if (*l
== "none") {
290 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
293 if (noneSeen
== false)
295 allCodes
.push_back(*l
);
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
);
309 // getArchitectures - Return Vector of prefered Architectures /*{{{*/
310 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) {
313 std::vector
<string
> static archs
;
314 if (likely(Cached
== true) && archs
.empty() == false)
317 archs
= _config
->FindVector("APT::Architectures");
318 string
const arch
= _config
->Find("APT::Architecture");
319 if (unlikely(arch
.empty() == true))
322 if (archs
.empty() == true ||
323 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
324 archs
.push_back(arch
);
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())
338 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
339 bool const Configuration::checkArchitecture(std::string
const &Arch
) {
342 std::vector
<std::string
> const archs
= getArchitectures(true);
343 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());
346 // setDefaultConfigurationForCompressors /*{{{*/
347 void 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");
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 */
358 std::vector
<APT::Configuration::Compressor
>
359 const Configuration::getCompressors(bool const Cached
) {
360 static std::vector
<APT::Configuration::Compressor
> compressors
;
361 if (compressors
.empty() == false) {
368 setDefaultConfigurationForCompressors();
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));
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")
385 compressors
.push_back(Compressor(c
->c_str(), std::string(".").append(*c
).c_str(), c
->c_str(), "-9", "-d", 100));
391 // getCompressorExtensions - supported data.tar extensions /*{{{*/
392 // ---------------------------------------------------------------------
394 std::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
);
404 // Compressor constructor /*{{{*/
405 // ---------------------------------------------------------------------
407 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
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
);