]>
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>
20 #include <sys/types.h>
29 // getCompressionTypes - Return Vector of usbale compressiontypes /*{{{*/
30 // ---------------------------------------------------------------------
31 /* return a vector of compression types in the prefered order. */
32 std::vector
<std::string
>
33 const Configuration::getCompressionTypes(bool const &Cached
) {
34 static std::vector
<std::string
> types
;
35 if (types
.empty() == false) {
42 // setup the defaults for the compressiontypes => method mapping
43 _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2");
44 _config
->CndSet("Acquire::CompressionTypes::xz","xz");
45 _config
->CndSet("Acquire::CompressionTypes::lzma","lzma");
46 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
48 setDefaultConfigurationForCompressors();
50 // accept non-list order as override setting for config settings on commandline
51 std::string
const overrideOrder
= _config
->Find("Acquire::CompressionTypes::Order","");
52 if (overrideOrder
.empty() == false)
53 types
.push_back(overrideOrder
);
55 // load the order setting into our vector
56 std::vector
<std::string
> const order
= _config
->FindVector("Acquire::CompressionTypes::Order");
57 for (std::vector
<std::string
>::const_iterator o
= order
.begin();
58 o
!= order
.end(); ++o
) {
59 if ((*o
).empty() == true)
61 // ignore types we have no method ready to use
62 if (_config
->Exists(std::string("Acquire::CompressionTypes::").append(*o
)) == false)
64 // ignore types we have no app ready to use
65 std::string
const appsetting
= std::string("Dir::Bin::").append(*o
);
66 if (_config
->Exists(appsetting
) == true) {
67 std::string
const app
= _config
->FindFile(appsetting
.c_str(), "");
68 if (app
.empty() == false && FileExists(app
) == false)
74 // move again over the option tree to add all missing compression types
75 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
79 for (; Types
!= 0; Types
= Types
->Next
) {
80 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
82 // ignore types we already have in the vector
83 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
85 // ignore types we have no app ready to use
86 std::string
const appsetting
= std::string("Dir::Bin::").append(Types
->Value
);
87 if (appsetting
.empty() == false && _config
->Exists(appsetting
) == true) {
88 std::string
const app
= _config
->FindFile(appsetting
.c_str(), "");
89 if (app
.empty() == false && FileExists(app
) == false)
92 types
.push_back(Types
->Tag
);
95 // add the special "uncompressed" type
96 if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end())
98 std::string
const uncompr
= _config
->FindFile("Dir::Bin::uncompressed", "");
99 if (uncompr
.empty() == true || FileExists(uncompr
) == true)
100 types
.push_back("uncompressed");
106 // GetLanguages - Return Vector of Language Codes /*{{{*/
107 // ---------------------------------------------------------------------
108 /* return a vector of language codes in the prefered order.
109 the special word "environment" will be replaced with the long and the short
110 code of the local settings and it will be insured that this will not add
111 duplicates. So in an german local the setting "environment, de_DE, en, de"
112 will result in "de_DE, de, en".
113 The special word "none" is the stopcode for the not-All code vector */
114 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
115 bool const &Cached
, char const ** const Locale
) {
118 // The detection is boring and has a lot of cornercases,
119 // so we cache the results to calculated it only once.
120 std::vector
<string
> static allCodes
;
121 std::vector
<string
> static codes
;
123 // we have something in the cache
124 if (codes
.empty() == false || allCodes
.empty() == false) {
125 if (Cached
== true) {
126 if(All
== true && allCodes
.empty() == false)
136 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
137 // so they will be all included in the Cache.
138 std::vector
<string
> builtin
;
139 DIR *D
= opendir(_config
->FindDir("Dir::State::lists").c_str());
141 builtin
.push_back("none");
142 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
)) {
143 string
const name
= Ent
->d_name
;
144 size_t const foundDash
= name
.rfind("-");
145 size_t const foundUnderscore
= name
.rfind("_", foundDash
);
146 if (foundDash
== string::npos
|| foundUnderscore
== string::npos
||
147 foundDash
<= foundUnderscore
||
148 name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation")
150 string
const c
= name
.substr(foundDash
+1);
151 if (unlikely(c
.empty() == true) || c
== "en")
153 // Skip unusual files, like backups or that alike
154 string::const_iterator s
= c
.begin();
155 for (;s
!= c
.end(); ++s
) {
156 if (isalpha(*s
) == 0 && *s
!= '_')
161 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
163 builtin
.push_back(c
);
168 // FIXME: Remove support for the old APT::Acquire::Translation
169 // it was undocumented and so it should be not very widthly used
170 string
const oldAcquire
= _config
->Find("APT::Acquire::Translation","");
171 if (oldAcquire
.empty() == false && oldAcquire
!= "environment") {
172 // TRANSLATORS: the two %s are APT configuration options
173 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
174 "APT::Acquire::Translation", "Acquire::Languages");
175 if (oldAcquire
!= "none")
176 codes
.push_back(oldAcquire
);
177 codes
.push_back("en");
179 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
180 b
!= builtin
.end(); ++b
)
181 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
182 allCodes
.push_back(*b
);
189 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
190 // we extract both, a long and a short code and then we will
191 // check if we actually need both (rare) or if the short is enough
192 string
const envMsg
= string(Locale
== 0 ? std::setlocale(LC_MESSAGES
, NULL
) : *Locale
);
193 size_t const lenShort
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2;
194 size_t const lenLong
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort
+ 3);
196 string
const envLong
= envMsg
.substr(0,lenLong
);
197 string
const envShort
= envLong
.substr(0,lenShort
);
199 // It is very likely we will need the environment codes later,
200 // so let us generate them now from LC_MESSAGES and LANGUAGE
201 std::vector
<string
> environment
;
202 if (envShort
!= "C") {
203 // take care of LC_MESSAGES
204 if (envLong
!= envShort
)
205 environment
.push_back(envLong
);
206 environment
.push_back(envShort
);
207 // take care of LANGUAGE
208 const char *language_env
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
209 string envLang
= Locale
== 0 ? language_env
: *(Locale
+1);
210 if (envLang
.empty() == false) {
211 std::vector
<string
> env
= VectorizeString(envLang
,':');
212 short addedLangs
= 0; // add a maximum of 3 fallbacks from the environment
213 for (std::vector
<string
>::const_iterator e
= env
.begin();
214 e
!= env
.end() && addedLangs
< 3; ++e
) {
215 if (unlikely(e
->empty() == true) || *e
== "en")
217 if (*e
== envLong
|| *e
== envShort
)
219 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
222 environment
.push_back(*e
);
226 environment
.push_back("en");
229 // Support settings like Acquire::Languages=none on the command line to
230 // override the configuration settings vector of languages.
231 string
const forceLang
= _config
->Find("Acquire::Languages","");
232 if (forceLang
.empty() == false) {
233 if (forceLang
== "environment") {
235 } else if (forceLang
!= "none")
236 codes
.push_back(forceLang
);
237 else //if (forceLang == "none")
240 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
241 b
!= builtin
.end(); ++b
)
242 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
243 allCodes
.push_back(*b
);
250 // cornercase: LANG=C, so we use only "en" Translation
251 if (envShort
== "C") {
252 allCodes
= codes
= environment
;
253 allCodes
.insert(allCodes
.end(), builtin
.begin(), builtin
.end());
260 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages");
261 // the default setting -> "environment, en"
262 if (lang
.empty() == true) {
264 if (envShort
!= "en")
265 codes
.push_back("en");
267 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
268 b
!= builtin
.end(); ++b
)
269 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
270 allCodes
.push_back(*b
);
277 // the configs define the order, so add the environment
278 // then needed and ensure the codes are not listed twice.
279 bool noneSeen
= false;
280 for (std::vector
<string
>::const_iterator l
= lang
.begin();
281 l
!= lang
.end(); ++l
) {
282 if (*l
== "environment") {
283 for (std::vector
<string
>::const_iterator e
= environment
.begin();
284 e
!= environment
.end(); ++e
) {
285 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end())
287 if (noneSeen
== false)
289 allCodes
.push_back(*e
);
292 } else if (*l
== "none") {
295 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
298 if (noneSeen
== false)
300 allCodes
.push_back(*l
);
303 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
304 b
!= builtin
.end(); ++b
)
305 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
306 allCodes
.push_back(*b
);
314 // getArchitectures - Return Vector of prefered 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 (unlikely(arch
.empty() == true))
328 // FIXME: It is a bit unclean to have debian specific code hereā¦
329 if (archs
.empty() == true) {
330 archs
.push_back(arch
);
331 string dpkgcall
= _config
->Find("Dir::Bin::dpkg", "dpkg");
332 std::vector
<string
> const dpkgoptions
= _config
->FindVector("DPkg::options");
333 for (std::vector
<string
>::const_iterator o
= dpkgoptions
.begin();
334 o
!= dpkgoptions
.end(); ++o
)
335 dpkgcall
.append(" ").append(*o
);
336 dpkgcall
.append(" --print-foreign-architectures 2> /dev/null");
337 FILE *dpkg
= popen(dpkgcall
.c_str(), "r");
340 if (fgets(buf
, sizeof(buf
), dpkg
) != NULL
) {
341 char* arch
= strtok(buf
, " ");
342 while (arch
!= NULL
) {
343 for (; isspace(*arch
) != 0; ++arch
);
344 if (arch
[0] != '\0') {
345 char const* archend
= arch
;
346 for (; isspace(*archend
) == 0 && *archend
!= '\0'; ++archend
);
347 archs
.push_back(string(arch
, (archend
- arch
)));
349 arch
= strtok(NULL
, " ");
357 if (archs
.empty() == true ||
358 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
359 archs
.insert(archs
.begin(), arch
);
361 // erase duplicates and empty strings
362 for (std::vector
<string
>::reverse_iterator a
= archs
.rbegin();
363 a
!= archs
.rend(); ++a
) {
364 if (a
->empty() == true || std::find(a
+ 1, archs
.rend(), *a
) != archs
.rend())
365 archs
.erase(a
.base()-1);
366 if (a
== archs
.rend())
373 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
374 bool const Configuration::checkArchitecture(std::string
const &Arch
) {
377 std::vector
<std::string
> const archs
= getArchitectures(true);
378 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());
381 // setDefaultConfigurationForCompressors /*{{{*/
382 void Configuration::setDefaultConfigurationForCompressors() {
383 // Set default application paths to check for optional compression types
384 _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
385 _config
->CndSet("Dir::Bin::xz", "/usr/bin/xz");
386 _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
389 // getCompressors - Return Vector of usbale compressors /*{{{*/
390 // ---------------------------------------------------------------------
391 /* return a vector of compressors used by apt-ftparchive in the
392 multicompress functionality or to detect data.tar files */
393 std::vector
<APT::Configuration::Compressor
>
394 const Configuration::getCompressors(bool const Cached
) {
395 static std::vector
<APT::Configuration::Compressor
> compressors
;
396 if (compressors
.empty() == false) {
403 setDefaultConfigurationForCompressors();
405 compressors
.push_back(Compressor(".", "", "", "", "", 1));
406 if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->FindFile("Dir::Bin::gzip")) == true)
407 compressors
.push_back(Compressor("gzip",".gz","gzip","-9n","-d",2));
408 if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->FindFile("Dir::Bin::bzip2")) == true)
409 compressors
.push_back(Compressor("bzip2",".bz2","bzip2","-9","-d",3));
410 if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->FindFile("Dir::Bin::lzma")) == true)
411 compressors
.push_back(Compressor("lzma",".lzma","lzma","-9","-d",4));
412 if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->FindFile("Dir::Bin::xz")) == true)
413 compressors
.push_back(Compressor("xz",".xz","xz","-6","-d",5));
415 std::vector
<std::string
> const comp
= _config
->FindVector("APT::Compressor");
416 for (std::vector
<std::string
>::const_iterator c
= comp
.begin();
417 c
!= comp
.end(); ++c
) {
418 if (*c
== "." || *c
== "gzip" || *c
== "bzip2" || *c
== "lzma" || *c
== "xz")
420 compressors
.push_back(Compressor(c
->c_str(), std::string(".").append(*c
).c_str(), c
->c_str(), "-9", "-d", 100));
426 // getCompressorExtensions - supported data.tar extensions /*{{{*/
427 // ---------------------------------------------------------------------
429 std::vector
<std::string
> const Configuration::getCompressorExtensions() {
430 std::vector
<APT::Configuration::Compressor
> const compressors
= getCompressors();
431 std::vector
<std::string
> ext
;
432 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressors
.begin();
433 c
!= compressors
.end(); ++c
)
434 if (c
->Extension
.empty() == false && c
->Extension
!= ".")
435 ext
.push_back(c
->Extension
);
439 // Compressor constructor /*{{{*/
440 // ---------------------------------------------------------------------
442 Configuration::Compressor::Compressor(char const *name
, char const *extension
,
444 char const *compressArg
, char const *uncompressArg
,
445 unsigned short const cost
) {
446 std::string
const config
= std::string("APT:Compressor::").append(name
).append("::");
447 Name
= _config
->Find(std::string(config
).append("Name"), name
);
448 Extension
= _config
->Find(std::string(config
).append("Extension"), extension
);
449 Binary
= _config
->Find(std::string(config
).append("Binary"), binary
);
450 Cost
= _config
->FindI(std::string(config
).append("Cost"), cost
);
451 std::string
const compConf
= std::string(config
).append("CompressArg");
452 if (_config
->Exists(compConf
) == true)
453 CompressArgs
= _config
->FindVector(compConf
);
454 else if (compressArg
!= NULL
)
455 CompressArgs
.push_back(compressArg
);
456 std::string
const uncompConf
= std::string(config
).append("UncompressArg");
457 if (_config
->Exists(uncompConf
) == true)
458 UncompressArgs
= _config
->FindVector(uncompConf
);
459 else if (uncompressArg
!= NULL
)
460 UncompressArgs
.push_back(uncompressArg
);