]>
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::lzma","lzma");
42 _config
->CndSet("Acquire::CompressionTypes::gz","gzip");
44 // Set default application paths to check for optional compression types
45 _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
46 _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
48 // accept non-list order as override setting for config settings on commandline
49 std::string
const overrideOrder
= _config
->Find("Acquire::CompressionTypes::Order","");
50 if (overrideOrder
.empty() == false)
51 types
.push_back(overrideOrder
);
53 // load the order setting into our vector
54 std::vector
<std::string
> const order
= _config
->FindVector("Acquire::CompressionTypes::Order");
55 for (std::vector
<std::string
>::const_iterator o
= order
.begin();
56 o
!= order
.end(); o
++) {
57 if ((*o
).empty() == true)
59 // ignore types we have no method ready to use
60 if (_config
->Exists(string("Acquire::CompressionTypes::").append(*o
)) == false)
62 // ignore types we have no app ready to use
63 string
const appsetting
= string("Dir::Bin::").append(*o
);
64 if (_config
->Exists(appsetting
) == true) {
65 std::string
const app
= _config
->FindFile(appsetting
.c_str(), "");
66 if (app
.empty() == false && FileExists(app
) == false)
72 // default to preferring gzip, so that compressed indexes work
74 types
.push_back("gz");
76 // move again over the option tree to add all missing compression types
77 ::Configuration::Item
const *Types
= _config
->Tree("Acquire::CompressionTypes");
81 for (; Types
!= 0; Types
= Types
->Next
) {
82 if (Types
->Tag
== "Order" || Types
->Tag
.empty() == true)
84 // ignore types we already have in the vector
85 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end())
87 // ignore types we have no app ready to use
88 string
const appsetting
= string("Dir::Bin::").append(Types
->Value
);
89 if (appsetting
.empty() == false && _config
->Exists(appsetting
) == true) {
90 std::string
const app
= _config
->FindFile(appsetting
.c_str(), "");
91 if (app
.empty() == false && FileExists(app
) == false)
94 types
.push_back(Types
->Tag
);
100 // GetLanguages - Return Vector of Language Codes /*{{{*/
101 // ---------------------------------------------------------------------
102 /* return a vector of language codes in the prefered order.
103 the special word "environment" will be replaced with the long and the short
104 code of the local settings and it will be insured that this will not add
105 duplicates. So in an german local the setting "environment, de_DE, en, de"
106 will result in "de_DE, de, en".
107 The special word "none" is the stopcode for the not-All code vector */
108 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
,
109 bool const &Cached
, char const ** const Locale
) {
112 // The detection is boring and has a lot of cornercases,
113 // so we cache the results to calculated it only once.
114 std::vector
<string
> static allCodes
;
115 std::vector
<string
> static codes
;
117 // we have something in the cache
118 if (codes
.empty() == false || allCodes
.empty() == false) {
119 if (Cached
== true) {
120 if(All
== true && allCodes
.empty() == false)
130 // Include all Language codes we have a Translation file for in /var/lib/apt/lists
131 // so they will be all included in the Cache.
132 std::vector
<string
> builtin
;
133 DIR *D
= opendir(_config
->FindDir("Dir::State::lists").c_str());
135 builtin
.push_back("none");
136 for (struct dirent
*Ent
= readdir(D
); Ent
!= 0; Ent
= readdir(D
)) {
137 string
const name
= Ent
->d_name
;
138 size_t const foundDash
= name
.rfind("-");
139 size_t const foundUnderscore
= name
.rfind("_");
140 if (foundDash
== string::npos
|| foundUnderscore
== string::npos
||
141 foundDash
<= foundUnderscore
||
142 name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation")
144 string
const c
= name
.substr(foundDash
+1);
145 if (unlikely(c
.empty() == true) || c
== "en")
147 // Skip unusual files, like backups or that alike
148 string::const_iterator s
= c
.begin();
149 for (;s
!= c
.end(); ++s
) {
150 if (isalpha(*s
) == 0)
155 if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end())
157 builtin
.push_back(c
);
162 // get the environment language codes: LC_MESSAGES (and later LANGUAGE)
163 // we extract both, a long and a short code and then we will
164 // check if we actually need both (rare) or if the short is enough
165 string
const envMsg
= string(Locale
== 0 ? std::setlocale(LC_MESSAGES
, NULL
) : *Locale
);
166 size_t const lenShort
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2;
167 size_t const lenLong
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort
+ 3);
169 string envLong
= envMsg
.substr(0,lenLong
);
170 string
const envShort
= envLong
.substr(0,lenShort
);
171 bool envLongIncluded
= true;
173 // first cornercase: LANG=C, so we use only "en" Translation
174 if (envLong
== "C") {
175 codes
.push_back("en");
177 allCodes
.insert(allCodes
.end(), builtin
.begin(), builtin
.end());
184 // to save the servers from unneeded queries, we only try also long codes
185 // for languages it is realistic to have a long code translation fileā¦
186 // TODO: Improve translation acquire system to drop them dynamic
187 char const *needLong
[] = { "cs", "en", "pt", "sv", "zh", NULL
};
188 if (envLong
!= envShort
) {
189 for (char const **l
= needLong
; *l
!= NULL
; l
++)
190 if (envShort
.compare(*l
) == 0) {
191 envLongIncluded
= false;
196 // we don't add the long code, but we allow the user to do so
197 if (envLongIncluded
== true)
200 // FIXME: Remove support for the old APT::Acquire::Translation
201 // it was undocumented and so it should be not very widthly used
202 string
const oldAcquire
= _config
->Find("APT::Acquire::Translation","");
203 if (oldAcquire
.empty() == false && oldAcquire
!= "environment") {
204 // TRANSLATORS: the two %s are APT configuration options
205 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.",
206 "APT::Acquire::Translation", "Acquire::Languages");
207 if (oldAcquire
!= "none")
208 codes
.push_back(oldAcquire
);
209 codes
.push_back("en");
211 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
212 b
!= builtin
.end(); ++b
)
213 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
214 allCodes
.push_back(*b
);
221 // It is very likely we will need to environment codes later,
222 // so let us generate them now from LC_MESSAGES and LANGUAGE
223 std::vector
<string
> environment
;
224 // take care of LC_MESSAGES
225 if (envLongIncluded
== false)
226 environment
.push_back(envLong
);
227 environment
.push_back(envShort
);
228 // take care of LANGUAGE
229 const char *language_env
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE");
230 string envLang
= Locale
== 0 ? language_env
: *(Locale
+1);
231 if (envLang
.empty() == false) {
232 std::vector
<string
> env
= VectorizeString(envLang
,':');
233 short addedLangs
= 0; // add a maximum of 3 fallbacks from the environment
234 for (std::vector
<string
>::const_iterator e
= env
.begin();
235 e
!= env
.end() && addedLangs
< 3; ++e
) {
236 if (unlikely(e
->empty() == true) || *e
== "en")
238 if (*e
== envLong
|| *e
== envShort
)
240 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end())
242 if (e
->find('_') != string::npos
) {
243 // Drop LongCodes here - ShortCodes are also included
244 string
const shorty
= e
->substr(0, e
->find('_'));
245 char const **n
= needLong
;
246 for (; *n
!= NULL
; ++n
)
253 environment
.push_back(*e
);
257 // Support settings like Acquire::Translation=none on the command line to
258 // override the configuration settings vector of languages.
259 string
const forceLang
= _config
->Find("Acquire::Languages","");
260 if (forceLang
.empty() == false) {
261 if (forceLang
== "environment") {
263 } else if (forceLang
!= "none")
264 codes
.push_back(forceLang
);
266 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
267 b
!= builtin
.end(); ++b
)
268 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
269 allCodes
.push_back(*b
);
276 std::vector
<string
> const lang
= _config
->FindVector("Acquire::Languages");
277 // the default setting -> "environment, en"
278 if (lang
.empty() == true) {
280 if (envShort
!= "en")
281 codes
.push_back("en");
283 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
284 b
!= builtin
.end(); ++b
)
285 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
286 allCodes
.push_back(*b
);
293 // the configs define the order, so add the environment
294 // then needed and ensure the codes are not listed twice.
295 bool noneSeen
= false;
296 for (std::vector
<string
>::const_iterator l
= lang
.begin();
297 l
!= lang
.end(); l
++) {
298 if (*l
== "environment") {
299 for (std::vector
<string
>::const_iterator e
= environment
.begin();
300 e
!= environment
.end(); ++e
) {
301 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end())
303 if (noneSeen
== false)
305 allCodes
.push_back(*e
);
308 } else if (*l
== "none") {
311 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end())
314 if (noneSeen
== false)
316 allCodes
.push_back(*l
);
319 for (std::vector
<string
>::const_iterator b
= builtin
.begin();
320 b
!= builtin
.end(); ++b
)
321 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end())
322 allCodes
.push_back(*b
);
330 // getArchitectures - Return Vector of prefered Architectures /*{{{*/
331 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) {
334 std::vector
<string
> static archs
;
335 if (likely(Cached
== true) && archs
.empty() == false)
338 archs
= _config
->FindVector("APT::Architectures");
339 string
const arch
= _config
->Find("APT::Architecture");
340 if (unlikely(arch
.empty() == true))
343 if (archs
.empty() == true ||
344 std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
345 archs
.push_back(arch
);
347 // erase duplicates and empty strings
348 for (std::vector
<string
>::reverse_iterator a
= archs
.rbegin();
349 a
!= archs
.rend(); ++a
) {
350 if (a
->empty() == true || std::find(a
+ 1, archs
.rend(), *a
) != archs
.rend())
351 archs
.erase(a
.base()-1);
352 if (a
== archs
.rend())
359 // checkArchitecture - are we interested in the given Architecture? /*{{{*/
360 bool const Configuration::checkArchitecture(std::string
const &Arch
) {
363 std::vector
<std::string
> const archs
= getArchitectures(true);
364 return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end());