]>
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/fileutl.h> 
  14 #include <apt-pkg/macros.h> 
  15 #include <apt-pkg/strutl.h> 
  17 #include <sys/types.h> 
  25 // getCompressionTypes - Return Vector of usbale compressiontypes       /*{{{*/ 
  26 // --------------------------------------------------------------------- 
  27 /* return a vector of compression types in the prefered order. */ 
  28 std::vector
<std::string
> 
  29 const Configuration::getCompressionTypes(bool const &Cached
) { 
  30         static std::vector
<std::string
> types
; 
  31         if (types
.empty() == false) { 
  38         // setup the defaults for the compressiontypes => method mapping 
  39         _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2"); 
  40         _config
->CndSet("Acquire::CompressionTypes::lzma","lzma"); 
  41         _config
->CndSet("Acquire::CompressionTypes::gz","gzip"); 
  43         // Set default application paths to check for optional compression types 
  44         _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma"); 
  45         _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2"); 
  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
); 
  95 // GetLanguages - Return Vector of Language Codes                       /*{{{*/ 
  96 // --------------------------------------------------------------------- 
  97 /* return a vector of language codes in the prefered order. 
  98    the special word "environment" will be replaced with the long and the short 
  99    code of the local settings and it will be insured that this will not add 
 100    duplicates. So in an german local the setting "environment, de_DE, en, de" 
 101    will result in "de_DE, de, en". 
 102    The special word "none" is the stopcode for the not-All code vector */ 
 103 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
, 
 104                                 bool const &Cached
, char const ** const Locale
) { 
 107         // The detection is boring and has a lot of cornercases, 
 108         // so we cache the results to calculated it only once. 
 109         std::vector
<string
> static allCodes
; 
 110         std::vector
<string
> static codes
; 
 112         // we have something in the cache 
 113         if (codes
.empty() == false || allCodes
.empty() == false) { 
 114                 if (Cached 
== true) { 
 115                         if(All 
== true && allCodes
.empty() == false) 
 125         // Include all Language codes we have a Translation file for in /var/lib/apt/lists 
 126         // so they will be all included in the Cache. 
 127         std::vector
<string
> builtin
; 
 128         DIR *D 
= opendir(_config
->FindDir("Dir::State::lists").c_str()); 
 130                 builtin
.push_back("none"); 
 131                 for (struct dirent 
*Ent 
= readdir(D
); Ent 
!= 0; Ent 
= readdir(D
)) { 
 132                         string 
const name 
= Ent
->d_name
; 
 133                         size_t const foundDash 
= name
.rfind("-"); 
 134                         size_t const foundUnderscore 
= name
.rfind("_"); 
 135                         if (foundDash 
== string::npos 
|| foundUnderscore 
== string::npos 
|| 
 136                             foundDash 
<= foundUnderscore 
|| 
 137                             name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation") 
 139                         string 
const c 
= name
.substr(foundDash
+1); 
 140                         if (unlikely(c
.empty() == true) || c 
== "en") 
 142                         // Skip unusual files, like backups or that alike 
 143                         string::const_iterator s 
= c
.begin(); 
 144                         for (;s 
!= c
.end(); ++s
) { 
 145                                 if (isalpha(*s
) == 0) 
 150                         if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end()) 
 152                         builtin
.push_back(c
); 
 157         // get the environment language codes: LC_MESSAGES (and later LANGUAGE) 
 158         // we extract both, a long and a short code and then we will 
 159         // check if we actually need both (rare) or if the short is enough 
 160         string 
const envMsg 
= string(Locale 
== 0 ? std::setlocale(LC_MESSAGES
, NULL
) : *Locale
); 
 161         size_t const lenShort 
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2; 
 162         size_t const lenLong 
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort 
+ 3); 
 164         string envLong 
= envMsg
.substr(0,lenLong
); 
 165         string 
const envShort 
= envLong
.substr(0,lenShort
); 
 166         bool envLongIncluded 
= true; 
 168         // first cornercase: LANG=C, so we use only "en" Translation 
 169         if (envLong 
== "C") { 
 170                 codes
.push_back("en"); 
 172                 allCodes
.insert(allCodes
.end(), builtin
.begin(), builtin
.end()); 
 179         // to save the servers from unneeded queries, we only try also long codes 
 180         // for languages it is realistic to have a long code translation file⦠
 181         // TODO: Improve translation acquire system to drop them dynamic 
 182         char const *needLong
[] = { "cs", "en", "pt", "sv", "zh", NULL 
}; 
 183         if (envLong 
!= envShort
) { 
 184                 for (char const **l 
= needLong
; *l 
!= NULL
; l
++) 
 185                         if (envShort
.compare(*l
) == 0) { 
 186                                 envLongIncluded 
= false; 
 191         // we don't add the long code, but we allow the user to do so 
 192         if (envLongIncluded 
== true) 
 195         // FIXME: Remove support for the old APT::Acquire::Translation 
 196         // it was undocumented and so it should be not very widthly used 
 197         string 
const oldAcquire 
= _config
->Find("APT::Acquire::Translation",""); 
 198         if (oldAcquire
.empty() == false && oldAcquire 
!= "environment") { 
 199                 if (oldAcquire 
!= "none") 
 200                         codes
.push_back(oldAcquire
); 
 201                 codes
.push_back("en"); 
 203                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 204                      b 
!= builtin
.end(); ++b
) 
 205                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 206                                 allCodes
.push_back(*b
); 
 213         // It is very likely we will need to environment codes later, 
 214         // so let us generate them now from LC_MESSAGES and LANGUAGE 
 215         std::vector
<string
> environment
; 
 216         // take care of LC_MESSAGES 
 217         if (envLongIncluded 
== false) 
 218                 environment
.push_back(envLong
); 
 219         environment
.push_back(envShort
); 
 220         // take care of LANGUAGE 
 221         const char *language_env 
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE"); 
 222         string envLang 
= Locale 
== 0 ? language_env 
: *(Locale
+1); 
 223         if (envLang
.empty() == false) { 
 224                 std::vector
<string
> env 
= ExplodeString(envLang
,':'); 
 225                 short addedLangs 
= 0; // add a maximum of 3 fallbacks from the environment 
 226                 for (std::vector
<string
>::const_iterator e 
= env
.begin(); 
 227                      e 
!= env
.end() && addedLangs 
< 3; ++e
) { 
 228                         if (unlikely(e
->empty() == true) || *e 
== "en") 
 230                         if (*e 
== envLong 
|| *e 
== envShort
) 
 232                         if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end()) 
 234                         if (e
->find('_') != string::npos
) { 
 235                                 // Drop LongCodes here - ShortCodes are also included 
 236                                 string 
const shorty 
= e
->substr(0, e
->find('_')); 
 237                                 char const **n 
= needLong
; 
 238                                 for (; *n 
!= NULL
; ++n
) 
 245                         environment
.push_back(*e
); 
 249         // Support settings like Acquire::Translation=none on the command line to 
 250         // override the configuration settings vector of languages. 
 251         string 
const forceLang 
= _config
->Find("Acquire::Languages",""); 
 252         if (forceLang
.empty() == false) { 
 253                 if (forceLang 
== "environment") { 
 255                 } else if (forceLang 
!= "none") 
 256                         codes
.push_back(forceLang
); 
 258                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 259                      b 
!= builtin
.end(); ++b
) 
 260                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 261                                 allCodes
.push_back(*b
); 
 268         std::vector
<string
> const lang 
= _config
->FindVector("Acquire::Languages"); 
 269         // the default setting -> "environment, en" 
 270         if (lang
.empty() == true) { 
 272                 if (envShort 
!= "en") 
 273                         codes
.push_back("en"); 
 275                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 276                      b 
!= builtin
.end(); ++b
) 
 277                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 278                                 allCodes
.push_back(*b
); 
 285         // the configs define the order, so add the environment 
 286         // then needed and ensure the codes are not listed twice. 
 287         bool noneSeen 
= false; 
 288         for (std::vector
<string
>::const_iterator l 
= lang
.begin(); 
 289              l 
!= lang
.end(); l
++) { 
 290                 if (*l 
== "environment") { 
 291                         for (std::vector
<string
>::const_iterator e 
= environment
.begin(); 
 292                              e 
!= environment
.end(); ++e
) { 
 293                                 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end()) 
 295                                 if (noneSeen 
== false) 
 297                                 allCodes
.push_back(*e
); 
 300                 } else if (*l 
== "none") { 
 303                 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end()) 
 306                 if (noneSeen 
== false) 
 308                 allCodes
.push_back(*l
); 
 311         for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 312              b 
!= builtin
.end(); ++b
) 
 313                 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 314                         allCodes
.push_back(*b
); 
 322 // getArchitectures - Return Vector of prefered Architectures           /*{{{*/ 
 323 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) { 
 326         std::vector
<string
> static archs
; 
 327         if (likely(Cached 
== true) && archs
.empty() == false) 
 330         string 
const arch 
= _config
->Find("APT::Architecture"); 
 331         archs 
= _config
->FindVector("APT::Architectures"); 
 332         if (archs
.empty() == true || 
 333             std::find(archs
.begin(), archs
.end(), arch
) == archs
.end()) 
 334                 archs
.push_back(arch
); 
 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());