]>
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> 
  27 // getCompressionTypes - Return Vector of usbale compressiontypes       /*{{{*/ 
  28 // --------------------------------------------------------------------- 
  29 /* return a vector of compression types in the prefered order. */ 
  30 std::vector
<std::string
> 
  31 const Configuration::getCompressionTypes(bool const &Cached
) { 
  32         static std::vector
<std::string
> types
; 
  33         if (types
.empty() == false) { 
  40         // setup the defaults for the compressiontypes => method mapping 
  41         _config
->CndSet("Acquire::CompressionTypes::bz2","bzip2"); 
  42         _config
->CndSet("Acquire::CompressionTypes::xz","xz"); 
  43         _config
->CndSet("Acquire::CompressionTypes::lzma","lzma"); 
  44         _config
->CndSet("Acquire::CompressionTypes::gz","gzip"); 
  46         setDefaultConfigurationForCompressors(); 
  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         // move again over the option tree to add all missing compression types 
  73         ::Configuration::Item 
const *Types 
= _config
->Tree("Acquire::CompressionTypes"); 
  77         for (; Types 
!= 0; Types 
= Types
->Next
) { 
  78                 if (Types
->Tag 
== "Order" || Types
->Tag
.empty() == true) 
  80                 // ignore types we already have in the vector 
  81                 if (std::find(types
.begin(),types
.end(),Types
->Tag
) != types
.end()) 
  83                 // ignore types we have no app ready to use 
  84                 string 
const appsetting 
= string("Dir::Bin::").append(Types
->Value
); 
  85                 if (appsetting
.empty() == false && _config
->Exists(appsetting
) == true) { 
  86                         std::string 
const app 
= _config
->FindFile(appsetting
.c_str(), ""); 
  87                         if (app
.empty() == false && FileExists(app
) == false) 
  90                 types
.push_back(Types
->Tag
); 
  93         // add the special "uncompressed" type 
  94         if (std::find(types
.begin(), types
.end(), "uncompressed") == types
.end()) 
  96                 string 
const uncompr 
= _config
->FindFile("Dir::Bin::uncompressed", ""); 
  97                 if (uncompr
.empty() == true || FileExists(uncompr
) == true) 
  98                         types
.push_back("uncompressed"); 
 104 // GetLanguages - Return Vector of Language Codes                       /*{{{*/ 
 105 // --------------------------------------------------------------------- 
 106 /* return a vector of language codes in the prefered order. 
 107    the special word "environment" will be replaced with the long and the short 
 108    code of the local settings and it will be insured that this will not add 
 109    duplicates. So in an german local the setting "environment, de_DE, en, de" 
 110    will result in "de_DE, de, en". 
 111    The special word "none" is the stopcode for the not-All code vector */ 
 112 std::vector
<std::string
> const Configuration::getLanguages(bool const &All
, 
 113                                 bool const &Cached
, char const ** const Locale
) { 
 116         // The detection is boring and has a lot of cornercases, 
 117         // so we cache the results to calculated it only once. 
 118         std::vector
<string
> static allCodes
; 
 119         std::vector
<string
> static codes
; 
 121         // we have something in the cache 
 122         if (codes
.empty() == false || allCodes
.empty() == false) { 
 123                 if (Cached 
== true) { 
 124                         if(All 
== true && allCodes
.empty() == false) 
 134         // Include all Language codes we have a Translation file for in /var/lib/apt/lists 
 135         // so they will be all included in the Cache. 
 136         std::vector
<string
> builtin
; 
 137         DIR *D 
= opendir(_config
->FindDir("Dir::State::lists").c_str()); 
 139                 builtin
.push_back("none"); 
 140                 for (struct dirent 
*Ent 
= readdir(D
); Ent 
!= 0; Ent 
= readdir(D
)) { 
 141                         string 
const name 
= Ent
->d_name
; 
 142                         size_t const foundDash 
= name
.rfind("-"); 
 143                         size_t const foundUnderscore 
= name
.rfind("_", foundDash
); 
 144                         if (foundDash 
== string::npos 
|| foundUnderscore 
== string::npos 
|| 
 145                             foundDash 
<= foundUnderscore 
|| 
 146                             name
.substr(foundUnderscore
+1, foundDash
-(foundUnderscore
+1)) != "Translation") 
 148                         string 
const c 
= name
.substr(foundDash
+1); 
 149                         if (unlikely(c
.empty() == true) || c 
== "en") 
 151                         // Skip unusual files, like backups or that alike 
 152                         string::const_iterator s 
= c
.begin(); 
 153                         for (;s 
!= c
.end(); ++s
) { 
 154                                 if (isalpha(*s
) == 0 && *s 
!= '_') 
 159                         if (std::find(builtin
.begin(), builtin
.end(), c
) != builtin
.end()) 
 161                         builtin
.push_back(c
); 
 166         // FIXME: Remove support for the old APT::Acquire::Translation 
 167         // it was undocumented and so it should be not very widthly used 
 168         string 
const oldAcquire 
= _config
->Find("APT::Acquire::Translation",""); 
 169         if (oldAcquire
.empty() == false && oldAcquire 
!= "environment") { 
 170                 // TRANSLATORS: the two %s are APT configuration options 
 171                 _error
->Notice("Option '%s' is deprecated. Please use '%s' instead, see 'man 5 apt.conf' for details.", 
 172                                 "APT::Acquire::Translation", "Acquire::Languages"); 
 173                 if (oldAcquire 
!= "none") 
 174                         codes
.push_back(oldAcquire
); 
 175                 codes
.push_back("en"); 
 177                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 178                      b 
!= builtin
.end(); ++b
) 
 179                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 180                                 allCodes
.push_back(*b
); 
 187         // get the environment language codes: LC_MESSAGES (and later LANGUAGE) 
 188         // we extract both, a long and a short code and then we will 
 189         // check if we actually need both (rare) or if the short is enough 
 190         string 
const envMsg 
= string(Locale 
== 0 ? std::setlocale(LC_MESSAGES
, NULL
) : *Locale
); 
 191         size_t const lenShort 
= (envMsg
.find('_') != string::npos
) ? envMsg
.find('_') : 2; 
 192         size_t const lenLong 
= (envMsg
.find_first_of(".@") != string::npos
) ? envMsg
.find_first_of(".@") : (lenShort 
+ 3); 
 194         string 
const envLong 
= envMsg
.substr(0,lenLong
); 
 195         string 
const envShort 
= envLong
.substr(0,lenShort
); 
 197         // It is very likely we will need the environment codes later, 
 198         // so let us generate them now from LC_MESSAGES and LANGUAGE 
 199         std::vector
<string
> environment
; 
 200         if (envShort 
!= "C") { 
 201                 // take care of LC_MESSAGES 
 202                 if (envLong 
!= envShort
) 
 203                         environment
.push_back(envLong
); 
 204                 environment
.push_back(envShort
); 
 205                 // take care of LANGUAGE 
 206                 const char *language_env 
= getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE"); 
 207                 string envLang 
= Locale 
== 0 ? language_env 
: *(Locale
+1); 
 208                 if (envLang
.empty() == false) { 
 209                         std::vector
<string
> env 
= VectorizeString(envLang
,':'); 
 210                         short addedLangs 
= 0; // add a maximum of 3 fallbacks from the environment 
 211                         for (std::vector
<string
>::const_iterator e 
= env
.begin(); 
 212                              e 
!= env
.end() && addedLangs 
< 3; ++e
) { 
 213                                 if (unlikely(e
->empty() == true) || *e 
== "en") 
 215                                 if (*e 
== envLong 
|| *e 
== envShort
) 
 217                                 if (std::find(environment
.begin(), environment
.end(), *e
) != environment
.end()) 
 220                                 environment
.push_back(*e
); 
 224                 environment
.push_back("en"); 
 227         // Support settings like Acquire::Languages=none on the command line to 
 228         // override the configuration settings vector of languages. 
 229         string 
const forceLang 
= _config
->Find("Acquire::Languages",""); 
 230         if (forceLang
.empty() == false) { 
 231                 if (forceLang 
== "environment") { 
 233                 } else if (forceLang 
!= "none") 
 234                         codes
.push_back(forceLang
); 
 235                 else //if (forceLang == "none") 
 238                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 239                      b 
!= builtin
.end(); ++b
) 
 240                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 241                                 allCodes
.push_back(*b
); 
 248         // cornercase: LANG=C, so we use only "en" Translation 
 249         if (envShort 
== "C") { 
 250                 allCodes 
= codes 
= environment
; 
 251                 allCodes
.insert(allCodes
.end(), builtin
.begin(), builtin
.end()); 
 258         std::vector
<string
> const lang 
= _config
->FindVector("Acquire::Languages"); 
 259         // the default setting -> "environment, en" 
 260         if (lang
.empty() == true) { 
 262                 if (envShort 
!= "en") 
 263                         codes
.push_back("en"); 
 265                 for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 266                      b 
!= builtin
.end(); ++b
) 
 267                         if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 268                                 allCodes
.push_back(*b
); 
 275         // the configs define the order, so add the environment 
 276         // then needed and ensure the codes are not listed twice. 
 277         bool noneSeen 
= false; 
 278         for (std::vector
<string
>::const_iterator l 
= lang
.begin(); 
 279              l 
!= lang
.end(); ++l
) { 
 280                 if (*l 
== "environment") { 
 281                         for (std::vector
<string
>::const_iterator e 
= environment
.begin(); 
 282                              e 
!= environment
.end(); ++e
) { 
 283                                 if (std::find(allCodes
.begin(), allCodes
.end(), *e
) != allCodes
.end()) 
 285                                 if (noneSeen 
== false) 
 287                                 allCodes
.push_back(*e
); 
 290                 } else if (*l 
== "none") { 
 293                 } else if (std::find(allCodes
.begin(), allCodes
.end(), *l
) != allCodes
.end()) 
 296                 if (noneSeen 
== false) 
 298                 allCodes
.push_back(*l
); 
 301         for (std::vector
<string
>::const_iterator b 
= builtin
.begin(); 
 302              b 
!= builtin
.end(); ++b
) 
 303                 if (std::find(allCodes
.begin(), allCodes
.end(), *b
) == allCodes
.end()) 
 304                         allCodes
.push_back(*b
); 
 312 // getArchitectures - Return Vector of prefered Architectures           /*{{{*/ 
 313 std::vector
<std::string
> const Configuration::getArchitectures(bool const &Cached
) { 
 316         std::vector
<string
> static archs
; 
 317         if (likely(Cached 
== true) && archs
.empty() == false) 
 320         string 
const arch 
= _config
->Find("APT::Architecture"); 
 321         archs 
= _config
->FindVector("APT::Architectures"); 
 323         if (unlikely(arch
.empty() == true)) 
 326         // FIXME: It is a bit unclean to have debian specific code here⦠
 327         if (archs
.empty() == true) { 
 328                 archs
.push_back(arch
); 
 329                 string dpkgcall 
= _config
->Find("Dir::Bin::dpkg", "dpkg"); 
 330                 std::vector
<string
> const dpkgoptions 
= _config
->FindVector("DPkg::options"); 
 331                 for (std::vector
<string
>::const_iterator o 
= dpkgoptions
.begin(); 
 332                      o 
!= dpkgoptions
.end(); ++o
) 
 333                         dpkgcall
.append(" ").append(*o
); 
 334                 dpkgcall
.append(" --print-foreign-architectures 2> /dev/null"); 
 335                 FILE *dpkg 
= popen(dpkgcall
.c_str(), "r"); 
 338                         while (fgets(buf
, sizeof(buf
), dpkg
) != NULL
) { 
 339                                 char* arch 
= strtok(buf
, " "); 
 340                                 while (arch 
!= NULL
) { 
 341                                         for (; isspace(*arch
) != 0; ++arch
); 
 342                                         if (arch
[0] != '\0') { 
 343                                                 char const* archend 
= arch
; 
 344                                                 for (; isspace(*archend
) == 0 && *archend 
!= '\0'; ++archend
); 
 345                                                 archs
.push_back(string(arch
, (archend 
- arch
))); 
 347                                         arch 
= strtok(NULL
, " "); 
 355         if (archs
.empty() == true || 
 356             std::find(archs
.begin(), archs
.end(), arch
) == archs
.end()) 
 357                 archs
.insert(archs
.begin(), arch
); 
 359         // erase duplicates and empty strings 
 360         for (std::vector
<string
>::reverse_iterator a 
= archs
.rbegin(); 
 361              a 
!= archs
.rend(); ++a
) { 
 362                 if (a
->empty() == true || std::find(a 
+ 1, archs
.rend(), *a
) != archs
.rend()) 
 363                         archs
.erase(a
.base()-1); 
 364                 if (a 
== archs
.rend()) 
 371 // checkArchitecture - are we interested in the given Architecture?     /*{{{*/ 
 372 bool const Configuration::checkArchitecture(std::string 
const &Arch
) { 
 375         std::vector
<std::string
> const archs 
= getArchitectures(true); 
 376         return (std::find(archs
.begin(), archs
.end(), Arch
) != archs
.end()); 
 379 // setDefaultConfigurationForCompressors                                /*{{{*/ 
 380 void Configuration::setDefaultConfigurationForCompressors() { 
 381         // Set default application paths to check for optional compression types 
 382         _config
->CndSet("Dir::Bin::lzma", "/usr/bin/lzma"); 
 383         _config
->CndSet("Dir::Bin::xz", "/usr/bin/xz"); 
 384         _config
->CndSet("Dir::Bin::bzip2", "/bin/bzip2"); 
 387 // getCompressors - Return Vector of usbale compressors                 /*{{{*/ 
 388 // --------------------------------------------------------------------- 
 389 /* return a vector of compressors used by apt-ftparchive in the 
 390    multicompress functionality or to detect data.tar files */ 
 391 std::vector
<APT::Configuration::Compressor
> 
 392 const Configuration::getCompressors(bool const Cached
) { 
 393         static std::vector
<APT::Configuration::Compressor
> compressors
; 
 394         if (compressors
.empty() == false) { 
 401         setDefaultConfigurationForCompressors(); 
 403         compressors
.push_back(Compressor(".", "", "", "", "", 1)); 
 404         if (_config
->Exists("Dir::Bin::gzip") == false || FileExists(_config
->FindFile("Dir::Bin::gzip")) == true) 
 405                 compressors
.push_back(Compressor("gzip",".gz","gzip","-9n","-d",2)); 
 406         if (_config
->Exists("Dir::Bin::bzip2") == false || FileExists(_config
->FindFile("Dir::Bin::bzip2")) == true) 
 407                 compressors
.push_back(Compressor("bzip2",".bz2","bzip2","-9","-d",3)); 
 408         if (_config
->Exists("Dir::Bin::lzma") == false || FileExists(_config
->FindFile("Dir::Bin::lzma")) == true) 
 409                 compressors
.push_back(Compressor("lzma",".lzma","lzma","-9","-d",4)); 
 410         if (_config
->Exists("Dir::Bin::xz") == false || FileExists(_config
->FindFile("Dir::Bin::xz")) == true) 
 411                 compressors
.push_back(Compressor("xz",".xz","xz","-6","-d",5)); 
 413         std::vector
<std::string
> const comp 
= _config
->FindVector("APT::Compressor"); 
 414         for (std::vector
<std::string
>::const_iterator c 
= comp
.begin(); 
 415              c 
!= comp
.end(); ++c
) { 
 416                 if (*c 
== "." || *c 
== "gzip" || *c 
== "bzip2" || *c 
== "lzma" || *c 
== "xz") 
 418                 compressors
.push_back(Compressor(c
->c_str(), std::string(".").append(*c
).c_str(), c
->c_str(), "-9", "-d", 100)); 
 424 // getCompressorExtensions - supported data.tar extensions              /*{{{*/ 
 425 // --------------------------------------------------------------------- 
 427 std::vector
<std::string
> const Configuration::getCompressorExtensions() { 
 428         std::vector
<APT::Configuration::Compressor
> const compressors 
= getCompressors(); 
 429         std::vector
<std::string
> ext
; 
 430         for (std::vector
<APT::Configuration::Compressor
>::const_iterator c 
= compressors
.begin(); 
 431              c 
!= compressors
.end(); ++c
) 
 432                 if (c
->Extension
.empty() == false && c
->Extension 
!= ".") 
 433                         ext
.push_back(c
->Extension
); 
 437 // Compressor constructor                                               /*{{{*/ 
 438 // --------------------------------------------------------------------- 
 440 Configuration::Compressor::Compressor(char const *name
, char const *extension
, 
 442                                       char const *compressArg
, char const *uncompressArg
, 
 443                                       unsigned short const cost
) { 
 444         std::string 
const config 
= string("APT:Compressor::").append(name
).append("::"); 
 445         Name 
= _config
->Find(std::string(config
).append("Name"), name
); 
 446         Extension 
= _config
->Find(std::string(config
).append("Extension"), extension
); 
 447         Binary 
= _config
->Find(std::string(config
).append("Binary"), binary
); 
 448         Cost 
= _config
->FindI(std::string(config
).append("Cost"), cost
); 
 449         std::string 
const compConf 
= std::string(config
).append("CompressArg"); 
 450         if (_config
->Exists(compConf
) == true) 
 451                 CompressArgs 
= _config
->FindVector(compConf
); 
 452         else if (compressArg 
!= NULL
) 
 453                 CompressArgs
.push_back(compressArg
); 
 454         std::string 
const uncompConf 
= std::string(config
).append("UncompressArg"); 
 455         if (_config
->Exists(uncompConf
) == true) 
 456                 UncompressArgs 
= _config
->FindVector(uncompConf
); 
 457         else if (uncompressArg 
!= NULL
) 
 458                 UncompressArgs
.push_back(uncompressArg
);