finally I saw the light, MediaAria2 now inherits MediaCurl, therefore
[platform/upstream/libzypp.git] / zypp / ZConfig.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/ZConfig.cc
10  *
11 */
12 extern "C"
13 {
14 #include <sys/utsname.h>
15 #include <unistd.h>
16 }
17 #include <iostream>
18 #include <fstream>
19 #include "zypp/base/Logger.h"
20 #include "zypp/base/IOStream.h"
21 #include "zypp/base/InputStream.h"
22 #include "zypp/base/String.h"
23
24 #include "zypp/ZConfig.h"
25 #include "zypp/ZYppFactory.h"
26 #include "zypp/PathInfo.h"
27 #include "zypp/parser/IniDict.h"
28
29 using namespace std;
30 using namespace zypp::filesystem;
31 using namespace zypp::parser;
32
33 #undef ZYPP_BASE_LOGGER_LOGGROUP
34 #define ZYPP_BASE_LOGGER_LOGGROUP "zconfig"
35
36 ///////////////////////////////////////////////////////////////////
37 namespace zypp
38 { /////////////////////////////////////////////////////////////////
39
40   ///////////////////////////////////////////////////////////////////
41   namespace
42   { /////////////////////////////////////////////////////////////////
43
44     /** Determine system architecture evaluating \c uname and \c /proc/cpuinfo.
45     */
46     Arch _autodetectSystemArchitecture()
47     {
48       struct ::utsname buf;
49       if ( ::uname( &buf ) < 0 )
50       {
51         ERR << "Can't determine system architecture" << endl;
52         return Arch_noarch;
53       }
54
55       Arch architecture( buf.machine );
56       MIL << "Uname architecture is '" << buf.machine << "'" << endl;
57
58       // some CPUs report i686 but dont implement cx8 and cmov
59       // check for both flags in /proc/cpuinfo and downgrade
60       // to i586 if either is missing (cf bug #18885)
61       if ( architecture == Arch_i686 )
62       {
63         std::ifstream cpuinfo( "/proc/cpuinfo" );
64         if ( cpuinfo )
65         {
66           for( iostr::EachLine in( cpuinfo ); in; in.next() )
67           {
68             if ( str::hasPrefix( *in, "flags" ) )
69             {
70               if (    in->find( "cx8" ) == std::string::npos
71                    || in->find( "cmov" ) == std::string::npos )
72               {
73                 architecture = Arch_i586;
74                 WAR << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
75               }
76               break;
77             }
78           }
79         }
80         else
81         {
82           ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl;
83         }
84       }
85       return architecture;
86     }
87
88      /** The locale to be used for texts and messages.
89      *
90      * For the encoding to be used the preference is
91      *
92      *    LC_ALL, LC_CTYPE, LANG
93      *
94      * For the language of the messages to be used, the preference is
95      *
96      *    LANGUAGE, LC_ALL, LC_MESSAGES, LANG
97      *
98      * Note that LANGUAGE can contain more than one locale name, it can be
99      * a list of locale names like for example
100      *
101      *    LANGUAGE=ja_JP.UTF-8:de_DE.UTF-8:fr_FR.UTF-8
102
103      * \todo Support dynamic fallbacklists defined by LANGUAGE
104      */
105     Locale _autodetectTextLocale()
106     {
107       Locale ret( "en" );
108       const char * envlist[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL };
109       for ( const char ** envvar = envlist; *envvar; ++envvar )
110       {
111         const char * envlang = getenv( *envvar );
112         if ( envlang )
113         {
114           std::string envstr( envlang );
115           if ( envstr != "POSIX" && envstr != "C" )
116           {
117             Locale lang( envstr );
118             if ( ! lang.code().empty() )
119             {
120               MIL << "Found " << *envvar << "=" << envstr << endl;
121               ret = lang;
122               break;
123             }
124           }
125         }
126       }
127       MIL << "Default text locale is '" << ret << "'" << endl;
128 #warning HACK AROUND BOOST_TEST_CATCH_SYSTEM_ERRORS
129       setenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS", "no", 1 );
130       return ret;
131     }
132
133    /////////////////////////////////////////////////////////////////
134   } // namespace zypp
135   ///////////////////////////////////////////////////////////////////
136
137   ///////////////////////////////////////////////////////////////////
138   //
139   //    CLASS NAME : ZConfig::Impl
140   //
141   /** ZConfig implementation.
142    * \todo Enrich section and entry definition by some comment
143    * (including the default setting and provide some method to
144    * write this into a sample zypp.conf.
145   */
146   class ZConfig::Impl
147   {
148     public:
149       Impl( const Pathname & override_r = Pathname() )
150         : _parsedZyppConf               ( override_r )
151         , cfg_arch                      ( defaultSystemArchitecture() )
152         , cfg_textLocale                ( defaultTextLocale() )
153         , repo_add_probe                ( false )
154         , repo_refresh_delay            ( 10 )
155         , download_use_deltarpm         ( true )
156         , download_use_deltarpm_always  ( false )
157         , download_max_concurrent_connections(2)
158         , download_min_download_speed(0)
159         , download_max_download_speed(0)
160         , download_max_silent_tries(5)
161         , solver_onlyRequires           ( false )
162         , apply_locks_file              ( true )
163
164       {
165         MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
166         // override_r has higest prio
167         // ZYPP_CONF might override /etc/zypp/zypp.conf
168         if ( _parsedZyppConf.empty() )
169         {
170           const char *env_confpath = getenv( "ZYPP_CONF" );
171           _parsedZyppConf = env_confpath ? env_confpath : "/etc/zypp/zypp.conf";
172         }
173         else
174         {
175           // Inject this into ZConfig. Be shure this is
176           // allocated via new. See: reconfigureZConfig
177           INT << "Reconfigure to " << _parsedZyppConf << endl;
178           ZConfig::instance()._pimpl.reset( this );
179         }
180         if ( PathInfo(_parsedZyppConf).isExist() )
181         {
182           parser::IniDict dict( _parsedZyppConf );
183           for ( IniDict::section_const_iterator sit = dict.sectionsBegin();
184                 sit != dict.sectionsEnd();
185                 ++sit )
186           {
187             string section(*sit);
188             //MIL << section << endl;
189             for ( IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
190                   it != dict.entriesEnd(*sit);
191                   ++it )
192             {
193               string entry(it->first);
194               string value(it->second);
195               //DBG << (*it).first << "=" << (*it).second << endl;
196               if ( section == "main" )
197               {
198                 if ( entry == "arch" )
199                 {
200                   Arch carch( value );
201                   if ( carch != cfg_arch )
202                   {
203                     WAR << "Overriding system architecture (" << cfg_arch << "): " << carch << endl;
204                     cfg_arch = carch;
205                   }
206                 }
207                 else if ( entry == "cachedir" )
208                 {
209                   cfg_cache_path = Pathname(value);
210                 }
211                 else if ( entry == "metadatadir" )
212                 {
213                   cfg_metadata_path = Pathname(value);
214                 }
215                 else if ( entry == "solvfilesdir" )
216                 {
217                   cfg_solvfiles_path = Pathname(value);
218                 }
219                 else if ( entry == "packagesdir" )
220                 {
221                   cfg_packages_path = Pathname(value);
222                 }
223                 else if ( entry == "configdir" )
224                 {
225                   cfg_config_path = Pathname(value);
226                 }
227                 else if ( entry == "reposdir" )
228                 {
229                   cfg_known_repos_path = Pathname(value);
230                 }
231                 else if ( entry == "repo.add.probe" )
232                 {
233                   repo_add_probe = str::strToBool( value, repo_add_probe );
234                 }
235                 else if ( entry == "repo.refresh.delay" )
236                 {
237                   str::strtonum(value, repo_refresh_delay);
238                 }
239                 else if ( entry == "download.use_deltarpm" )
240                 {
241                   download_use_deltarpm = str::strToBool( value, download_use_deltarpm );
242                 }
243                 else if ( entry == "download.use_deltarpm.always" )
244                 {
245                   download_use_deltarpm_always = str::strToBool( value, download_use_deltarpm_always );
246                 }
247                 else if ( entry == "download.max_concurrent_connections" )
248                 {
249                   str::strtonum(value, download_max_concurrent_connections);
250                 }
251                 else if ( entry == "download.min_download_speed" )
252                 {
253                   str::strtonum(value, download_min_download_speed);
254                 }
255                 else if ( entry == "download.max_download_speed" )
256                 {
257                   str::strtonum(value, download_max_download_speed);
258                 }
259                 else if ( entry == "download.max_silent_tries" )
260                 {
261                   str::strtonum(value, download_max_silent_tries);
262                 }
263                 else if ( entry == "vendordir" )
264                 {
265                   cfg_vendor_path = Pathname(value);
266                 }
267                 else if ( entry == "productsdir" )
268                 {
269                   WAR << "Deprecated entry 'productsdir=': This locations is no longer used or supported." << endl;
270                   cfg_products_path = Pathname(value);
271                 }
272                 else if ( entry == "solver.onlyRequires" )
273                 {
274                   solver_onlyRequires = str::strToBool( value, solver_onlyRequires );
275                 }
276                 else if ( entry == "solver.checkSystemFile" )
277                 {
278                   solver_checkSystemFile = Pathname(value);
279                 }
280                 else if ( entry == "multiversion" )
281                 {
282                   std::list<std::string> multi;
283                   str::split( value, back_inserter(multi), ", \t" );
284                   for ( std::list<string>::const_iterator it = multi.begin();
285                         it != multi.end(); it++) {
286                       multiversion.insert (IdString(*it));
287                   }
288                 }
289                 else if ( entry == "locksfile.path" )
290                 {
291                   locks_file = Pathname(value);
292                 }
293                 else if ( entry == "locksfile.apply" )
294                 {
295                   apply_locks_file = str::strToBool( value, apply_locks_file );
296                 }
297                 else if ( entry == "update.datadir" )
298                 {
299                   update_data_path = Pathname(value);
300                 }
301                 else if ( entry == "update.scriptsdir" )
302                 {
303                   update_scripts_path = Pathname(value);
304                 }
305                 else if ( entry == "update.messagessdir" )
306                 {
307                   update_messages_path = Pathname(value);
308                 }
309                 else if ( entry == "rpm.install.excludedocs" )
310                 {
311                   rpmInstallFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS );
312                 }
313                 else if ( entry == "history.logfile" )
314                 {
315                   history_log_path = Pathname(value);
316                 }
317                 else if ( entry == "credentials.global.dir" )
318                 {
319                   credentials_global_dir_path = Pathname(value);
320                 }
321                 else if ( entry == "credentials.global.file" )
322                 {
323                   credentials_global_file_path = Pathname(value);
324                 }
325               }
326             }
327           }
328         }
329         else
330         {
331           MIL << _parsedZyppConf << " not found, using defaults instead." << endl;
332           _parsedZyppConf.extend( " (NOT FOUND)" );
333         }
334
335         // legacy:
336         if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
337         {
338           Arch carch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
339           if ( carch != cfg_arch )
340           {
341             WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Overriding system architecture (" << cfg_arch << "): " << carch << endl;
342             cfg_arch = carch;
343           }
344         }
345         MIL << "ZConfig singleton created." << endl;
346       }
347
348       ~Impl()
349       {}
350
351     public:
352     /** Remember any parsed zypp.conf. */
353     Pathname _parsedZyppConf;
354
355     Arch     cfg_arch;
356     Locale   cfg_textLocale;
357
358     Pathname cfg_cache_path;
359     Pathname cfg_metadata_path;
360     Pathname cfg_solvfiles_path;
361     Pathname cfg_packages_path;
362
363     Pathname cfg_config_path;
364     Pathname cfg_known_repos_path;
365     Pathname cfg_known_services_path;
366     Pathname cfg_vendor_path;
367     Pathname cfg_products_path;
368     Pathname locks_file;
369
370     Pathname update_data_path;
371     Pathname update_scripts_path;
372     Pathname update_messages_path;
373
374     bool repo_add_probe;
375     unsigned repo_refresh_delay;
376
377     bool download_use_deltarpm;
378     bool download_use_deltarpm_always;
379
380     int download_max_concurrent_connections;
381     int download_min_download_speed;
382     int download_max_download_speed;
383     int download_max_silent_tries;
384
385     bool solver_onlyRequires;
386     Pathname solver_checkSystemFile;
387
388     std::set<IdString> multiversion;
389
390     bool apply_locks_file;
391
392     target::rpm::RpmInstFlags rpmInstallFlags;
393
394     Pathname history_log_path;
395     Pathname credentials_global_dir_path;
396     Pathname credentials_global_file_path;
397   };
398   ///////////////////////////////////////////////////////////////////
399
400   // Backdoor to redirect ZConfig from within the running
401   // TEST-application. HANDLE WITH CARE!
402   void reconfigureZConfig( const Pathname & override_r )
403   {
404     // ctor puts itself unter smart pointer control.
405     new ZConfig::Impl( override_r );
406   }
407
408   ///////////////////////////////////////////////////////////////////
409   //
410   //    METHOD NAME : ZConfig::instance
411   //    METHOD TYPE : ZConfig &
412   //
413   ZConfig & ZConfig::instance()
414   {
415     static ZConfig _instance; // The singleton
416     return _instance;
417   }
418
419   ///////////////////////////////////////////////////////////////////
420   //
421   //    METHOD NAME : ZConfig::ZConfig
422   //    METHOD TYPE : Ctor
423   //
424   ZConfig::ZConfig()
425   : _pimpl( new Impl )
426   {
427     about( MIL);
428   }
429
430   ///////////////////////////////////////////////////////////////////
431   //
432   //    METHOD NAME : ZConfig::~ZConfig
433   //    METHOD TYPE : Dtor
434   //
435   ZConfig::~ZConfig( )
436   {}
437
438   ///////////////////////////////////////////////////////////////////
439   //
440   // system architecture
441   //
442   ///////////////////////////////////////////////////////////////////
443
444   Arch ZConfig::defaultSystemArchitecture()
445   {
446     static Arch _val( _autodetectSystemArchitecture() );
447     return _val;
448   }
449
450   Arch ZConfig::systemArchitecture() const
451   { return _pimpl->cfg_arch; }
452
453   void ZConfig::setSystemArchitecture( const Arch & arch_r )
454   {
455     if ( arch_r != _pimpl->cfg_arch )
456     {
457       WAR << "Overriding system architecture (" << _pimpl->cfg_arch << "): " << arch_r << endl;
458       _pimpl->cfg_arch = arch_r;
459     }
460   }
461
462   ///////////////////////////////////////////////////////////////////
463   //
464   // text locale
465   //
466   ///////////////////////////////////////////////////////////////////
467
468   Locale ZConfig::defaultTextLocale()
469   {
470     static Locale _val( _autodetectTextLocale() );
471     return _val;
472   }
473
474   Locale ZConfig::textLocale() const
475   { return _pimpl->cfg_textLocale; }
476
477   void ZConfig::setTextLocale( const Locale & locale_r )
478   {
479     if ( locale_r != _pimpl->cfg_textLocale )
480     {
481       WAR << "Overriding text locale (" << _pimpl->cfg_textLocale << "): " << locale_r << endl;
482       _pimpl->cfg_textLocale = locale_r;
483     }
484   }
485
486   ///////////////////////////////////////////////////////////////////
487
488   Pathname ZConfig::repoCachePath() const
489   {
490     return ( _pimpl->cfg_cache_path.empty()
491         ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path );
492   }
493
494   Pathname ZConfig::repoMetadataPath() const
495   {
496     return ( _pimpl->cfg_metadata_path.empty()
497         ? (repoCachePath()/"raw") : _pimpl->cfg_metadata_path );
498   }
499
500   Pathname ZConfig::repoSolvfilesPath() const
501   {
502     return ( _pimpl->cfg_solvfiles_path.empty()
503         ? (repoCachePath()/"solv") : _pimpl->cfg_solvfiles_path );
504   }
505
506   Pathname ZConfig::repoPackagesPath() const
507   {
508     return ( _pimpl->cfg_packages_path.empty()
509         ? (repoCachePath()/"packages") : _pimpl->cfg_packages_path );
510   }
511
512   ///////////////////////////////////////////////////////////////////
513
514   Pathname ZConfig::configPath() const
515   {
516     return ( _pimpl->cfg_config_path.empty()
517         ? Pathname("/etc/zypp") : _pimpl->cfg_config_path );
518   }
519
520   Pathname ZConfig::knownReposPath() const
521   {
522     return ( _pimpl->cfg_known_repos_path.empty()
523         ? (configPath()/"repos.d") : _pimpl->cfg_known_repos_path );
524   }
525
526   Pathname ZConfig::knownServicesPath() const
527   {
528     return ( _pimpl->cfg_known_services_path.empty()
529         ? (configPath()/"services.d") : _pimpl->cfg_known_repos_path );
530   }
531
532   Pathname ZConfig::vendorPath() const
533   {
534     return ( _pimpl->cfg_vendor_path.empty()
535         ? (configPath()/"vendors.d") : _pimpl->cfg_vendor_path );
536   }
537
538   Pathname ZConfig::productsPath() const
539   {
540     return ( _pimpl->cfg_products_path.empty()
541         ? (configPath()/"products.d") : _pimpl->cfg_products_path );
542   }
543
544   Pathname ZConfig::locksFile() const
545   {
546     return ( _pimpl->locks_file.empty()
547         ? (configPath()/"locks") : _pimpl->locks_file );
548   }
549
550   ///////////////////////////////////////////////////////////////////
551
552   bool ZConfig::repo_add_probe() const
553   {
554     return _pimpl->repo_add_probe;
555   }
556
557   unsigned ZConfig::repo_refresh_delay() const
558   {
559     return _pimpl->repo_refresh_delay;
560   }
561
562   bool ZConfig::download_use_deltarpm() const
563   { return _pimpl->download_use_deltarpm; }
564
565   bool ZConfig::download_use_deltarpm_always() const
566   { return download_use_deltarpm() && _pimpl->download_use_deltarpm_always; }
567
568   long ZConfig::download_max_concurrent_connections() const
569   { return _pimpl->download_max_concurrent_connections; }
570         
571   long ZConfig::download_min_download_speed() const
572   { return _pimpl->download_min_download_speed; }
573     
574   long ZConfig::download_max_download_speed() const
575   { return _pimpl->download_max_download_speed; }
576
577   long ZConfig::download_max_silent_tries() const
578   { return _pimpl->download_max_silent_tries; }
579
580   bool ZConfig::solver_onlyRequires() const
581   { return _pimpl->solver_onlyRequires; }
582
583   Pathname ZConfig::solver_checkSystemFile() const
584   { return _pimpl->solver_checkSystemFile; }
585
586   std::set<IdString> ZConfig::multiversion() const
587   { return _pimpl->multiversion; }
588
589   void ZConfig::addMultiversion(std::string &name)
590   { _pimpl->multiversion.insert(IdString(name)); }
591
592   bool ZConfig::removeMultiversion(std::string &name)
593   { return _pimpl->multiversion.erase(IdString(name)); }
594
595   bool ZConfig::apply_locks_file() const
596   {
597     return _pimpl->apply_locks_file;
598   }
599
600   Pathname ZConfig::update_dataPath() const
601   {
602     return ( _pimpl->update_data_path.empty()
603         ? Pathname("/var/adm") : _pimpl->update_data_path );
604   }
605
606   Pathname ZConfig::update_messagesPath() const
607   {
608     return ( _pimpl->update_messages_path.empty()
609              ? Pathname(update_dataPath()/"update-messages") : _pimpl->update_messages_path );
610   }
611
612
613   Pathname ZConfig::update_scriptsPath() const
614   {
615     return ( _pimpl->update_scripts_path.empty()
616              ? Pathname(update_dataPath()/"update-scripts") : _pimpl->update_scripts_path );
617   }
618
619   ///////////////////////////////////////////////////////////////////
620
621   target::rpm::RpmInstFlags ZConfig::rpmInstallFlags() const
622   { return _pimpl->rpmInstallFlags; }
623
624
625   Pathname ZConfig::historyLogFile() const
626   {
627     return ( _pimpl->history_log_path.empty() ?
628         Pathname("/var/log/zypp/history") : _pimpl->history_log_path );
629   }
630
631
632   Pathname ZConfig::credentialsGlobalDir() const
633   {
634     return ( _pimpl->credentials_global_dir_path.empty() ?
635         Pathname("/etc/zypp/credentials.d") : _pimpl->credentials_global_dir_path );
636   }
637
638   Pathname ZConfig::credentialsGlobalFile() const
639   {
640     return ( _pimpl->credentials_global_file_path.empty() ?
641         Pathname("/etc/zypp/credentials.cat") : _pimpl->credentials_global_file_path );
642   }
643
644   ///////////////////////////////////////////////////////////////////
645
646   std::ostream & ZConfig::about( std::ostream & str ) const
647   {
648     str << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
649     str << "zypp.conf: '" << _pimpl->_parsedZyppConf << "'" << endl;
650     str << "TextLocale: '" << textLocale() << "' (" << defaultTextLocale() << ")" << endl;
651     str << "SystemArchitecture: '" << systemArchitecture() << "' (" << defaultSystemArchitecture() << ")" << endl;
652     return str;
653   }
654
655   /////////////////////////////////////////////////////////////////
656 } // namespace zypp
657 ///////////////////////////////////////////////////////////////////