Cleanup and remove deprecated interface methods
[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   /** Mutable option with initial value. */
138   template<class _Tp, _Tp _Initial>
139       struct Option
140       {
141         typedef _Tp value_type;
142
143         /** Default ctor sets _Initial. */
144         Option()
145           : _val( _Initial )
146         {}
147
148         /** Get the value.  */
149         value_type get() const
150         { return _val; }
151
152         /** Set a new value.  */
153         void set( const value_type & newval_r )
154         { _val = newval_r; }
155
156         private:
157           value_type _val;
158       };
159
160   /** Mutable option with initial value also remembering a config value. */
161   template<class _Tp, _Tp _Initial>
162       struct DefaultOption : public Option<_Tp,_Initial>
163       {
164         typedef _Tp                  value_type;
165         typedef Option<_Tp,_Initial> option_type;
166
167         /** Reset value to the current default. */
168         void restoreToDefault()
169         { this->set( _default.get() ); }
170
171         /** Reset value to a new default. */
172         void restoreToDefault( const value_type & newval_r )
173         { setDefault( newval_r ); restoreToDefault(); }
174
175         /** Get the current default value. */
176         value_type getDefault() const
177         { return _default.get(); }
178
179         /** Set a new default value. */
180         void setDefault( const value_type & newval_r )
181         { _default.set( newval_r ); }
182
183         private:
184           option_type _default;
185       };
186
187   ///////////////////////////////////////////////////////////////////
188   //
189   //    CLASS NAME : ZConfig::Impl
190   //
191   /** ZConfig implementation.
192    * \todo Enrich section and entry definition by some comment
193    * (including the default setting and provide some method to
194    * write this into a sample zypp.conf.
195   */
196   class ZConfig::Impl
197   {
198     public:
199       Impl( const Pathname & override_r = Pathname() )
200         : _parsedZyppConf               ( override_r )
201         , cfg_arch                      ( defaultSystemArchitecture() )
202         , cfg_textLocale                ( defaultTextLocale() )
203         , repo_add_probe                ( false )
204         , repo_refresh_delay            ( 10 )
205         , download_use_deltarpm         ( true )
206         , download_use_deltarpm_always  ( false )
207         , download_max_concurrent_connections(2)
208         , download_min_download_speed(0)
209         , download_max_download_speed(0)
210         , download_max_silent_tries(5)
211         , apply_locks_file              ( true )
212
213       {
214         MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
215         // override_r has higest prio
216         // ZYPP_CONF might override /etc/zypp/zypp.conf
217         if ( _parsedZyppConf.empty() )
218         {
219           const char *env_confpath = getenv( "ZYPP_CONF" );
220           _parsedZyppConf = env_confpath ? env_confpath : "/etc/zypp/zypp.conf";
221         }
222         else
223         {
224           // Inject this into ZConfig. Be shure this is
225           // allocated via new. See: reconfigureZConfig
226           INT << "Reconfigure to " << _parsedZyppConf << endl;
227           ZConfig::instance()._pimpl.reset( this );
228         }
229         if ( PathInfo(_parsedZyppConf).isExist() )
230         {
231           parser::IniDict dict( _parsedZyppConf );
232           for ( IniDict::section_const_iterator sit = dict.sectionsBegin();
233                 sit != dict.sectionsEnd();
234                 ++sit )
235           {
236             string section(*sit);
237             //MIL << section << endl;
238             for ( IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
239                   it != dict.entriesEnd(*sit);
240                   ++it )
241             {
242               string entry(it->first);
243               string value(it->second);
244               //DBG << (*it).first << "=" << (*it).second << endl;
245               if ( section == "main" )
246               {
247                 if ( entry == "arch" )
248                 {
249                   Arch carch( value );
250                   if ( carch != cfg_arch )
251                   {
252                     WAR << "Overriding system architecture (" << cfg_arch << "): " << carch << endl;
253                     cfg_arch = carch;
254                   }
255                 }
256                 else if ( entry == "cachedir" )
257                 {
258                   cfg_cache_path = Pathname(value);
259                 }
260                 else if ( entry == "metadatadir" )
261                 {
262                   cfg_metadata_path = Pathname(value);
263                 }
264                 else if ( entry == "solvfilesdir" )
265                 {
266                   cfg_solvfiles_path = Pathname(value);
267                 }
268                 else if ( entry == "packagesdir" )
269                 {
270                   cfg_packages_path = Pathname(value);
271                 }
272                 else if ( entry == "configdir" )
273                 {
274                   cfg_config_path = Pathname(value);
275                 }
276                 else if ( entry == "reposdir" )
277                 {
278                   cfg_known_repos_path = Pathname(value);
279                 }
280                 else if ( entry == "servicesdir" )
281                 {
282                   cfg_known_services_path = Pathname(value);
283                 }
284                 else if ( entry == "repo.add.probe" )
285                 {
286                   repo_add_probe = str::strToBool( value, repo_add_probe );
287                 }
288                 else if ( entry == "repo.refresh.delay" )
289                 {
290                   str::strtonum(value, repo_refresh_delay);
291                 }
292                 else if ( entry == "download.use_deltarpm" )
293                 {
294                   download_use_deltarpm = str::strToBool( value, download_use_deltarpm );
295                 }
296                 else if ( entry == "download.use_deltarpm.always" )
297                 {
298                   download_use_deltarpm_always = str::strToBool( value, download_use_deltarpm_always );
299                 }
300                 else if ( entry == "download.media_preference" )
301                 {
302                   download_media_prefer_download.restoreToDefault( str::compareCI( value, "volatile" ) != 0 );
303                 }
304                 else if ( entry == "download.max_concurrent_connections" )
305                 {
306                   str::strtonum(value, download_max_concurrent_connections);
307                 }
308                 else if ( entry == "download.min_download_speed" )
309                 {
310                   str::strtonum(value, download_min_download_speed);
311                 }
312                 else if ( entry == "download.max_download_speed" )
313                 {
314                   str::strtonum(value, download_max_download_speed);
315                 }
316                 else if ( entry == "download.max_silent_tries" )
317                 {
318                   str::strtonum(value, download_max_silent_tries);
319                 }
320                 else if ( entry == "vendordir" )
321                 {
322                   cfg_vendor_path = Pathname(value);
323                 }
324                 else if ( entry == "solver.onlyRequires" )
325                 {
326                   solver_onlyRequires.set( str::strToBool( value, solver_onlyRequires.get() ) );
327                 }
328                 else if ( entry == "solver.allowVendorChange" )
329                 {
330                   solver_allowVendorChange.set( str::strToBool( value, solver_allowVendorChange.get() ) );
331                 }
332                 else if ( entry == "solver.checkSystemFile" )
333                 {
334                   solver_checkSystemFile = Pathname(value);
335                 }
336                 else if ( entry == "multiversion" )
337                 {
338                   std::list<std::string> multi;
339                   str::split( value, back_inserter(multi), ", \t" );
340                   for ( std::list<string>::const_iterator it = multi.begin();
341                         it != multi.end(); it++) {
342                       multiversion.insert (IdString(*it));
343                   }
344                 }
345                 else if ( entry == "locksfile.path" )
346                 {
347                   locks_file = Pathname(value);
348                 }
349                 else if ( entry == "locksfile.apply" )
350                 {
351                   apply_locks_file = str::strToBool( value, apply_locks_file );
352                 }
353                 else if ( entry == "update.datadir" )
354                 {
355                   update_data_path = Pathname(value);
356                 }
357                 else if ( entry == "update.scriptsdir" )
358                 {
359                   update_scripts_path = Pathname(value);
360                 }
361                 else if ( entry == "update.messagessdir" )
362                 {
363                   update_messages_path = Pathname(value);
364                 }
365                 else if ( entry == "rpm.install.excludedocs" )
366                 {
367                   rpmInstallFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS );
368                 }
369                 else if ( entry == "history.logfile" )
370                 {
371                   history_log_path = Pathname(value);
372                 }
373                 else if ( entry == "credentials.global.dir" )
374                 {
375                   credentials_global_dir_path = Pathname(value);
376                 }
377                 else if ( entry == "credentials.global.file" )
378                 {
379                   credentials_global_file_path = Pathname(value);
380                 }
381               }
382             }
383           }
384         }
385         else
386         {
387           MIL << _parsedZyppConf << " not found, using defaults instead." << endl;
388           _parsedZyppConf.extend( " (NOT FOUND)" );
389         }
390
391         // legacy:
392         if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
393         {
394           Arch carch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
395           if ( carch != cfg_arch )
396           {
397             WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Overriding system architecture (" << cfg_arch << "): " << carch << endl;
398             cfg_arch = carch;
399           }
400         }
401         MIL << "ZConfig singleton created." << endl;
402       }
403
404       ~Impl()
405       {}
406
407     public:
408     /** Remember any parsed zypp.conf. */
409     Pathname _parsedZyppConf;
410
411     Arch     cfg_arch;
412     Locale   cfg_textLocale;
413
414     Pathname cfg_cache_path;
415     Pathname cfg_metadata_path;
416     Pathname cfg_solvfiles_path;
417     Pathname cfg_packages_path;
418
419     Pathname cfg_config_path;
420     Pathname cfg_known_repos_path;
421     Pathname cfg_known_services_path;
422     Pathname cfg_vendor_path;
423     Pathname locks_file;
424
425     Pathname update_data_path;
426     Pathname update_scripts_path;
427     Pathname update_messages_path;
428
429     bool repo_add_probe;
430     unsigned repo_refresh_delay;
431
432     bool download_use_deltarpm;
433     bool download_use_deltarpm_always;
434     DefaultOption<bool,true> download_media_prefer_download;
435
436     int download_max_concurrent_connections;
437     int download_min_download_speed;
438     int download_max_download_speed;
439     int download_max_silent_tries;
440
441     Option<bool,false> solver_onlyRequires;
442     Option<bool,false> solver_allowVendorChange;
443     Pathname solver_checkSystemFile;
444
445     std::set<IdString> multiversion;
446
447     bool apply_locks_file;
448
449     target::rpm::RpmInstFlags rpmInstallFlags;
450
451     Pathname history_log_path;
452     Pathname credentials_global_dir_path;
453     Pathname credentials_global_file_path;
454   };
455   ///////////////////////////////////////////////////////////////////
456
457   // Backdoor to redirect ZConfig from within the running
458   // TEST-application. HANDLE WITH CARE!
459   void reconfigureZConfig( const Pathname & override_r )
460   {
461     // ctor puts itself unter smart pointer control.
462     new ZConfig::Impl( override_r );
463   }
464
465   ///////////////////////////////////////////////////////////////////
466   //
467   //    METHOD NAME : ZConfig::instance
468   //    METHOD TYPE : ZConfig &
469   //
470   ZConfig & ZConfig::instance()
471   {
472     static ZConfig _instance; // The singleton
473     return _instance;
474   }
475
476   ///////////////////////////////////////////////////////////////////
477   //
478   //    METHOD NAME : ZConfig::ZConfig
479   //    METHOD TYPE : Ctor
480   //
481   ZConfig::ZConfig()
482   : _pimpl( new Impl )
483   {
484     about( MIL);
485   }
486
487   ///////////////////////////////////////////////////////////////////
488   //
489   //    METHOD NAME : ZConfig::~ZConfig
490   //    METHOD TYPE : Dtor
491   //
492   ZConfig::~ZConfig( )
493   {}
494
495   ///////////////////////////////////////////////////////////////////
496   //
497   // system architecture
498   //
499   ///////////////////////////////////////////////////////////////////
500
501   Arch ZConfig::defaultSystemArchitecture()
502   {
503     static Arch _val( _autodetectSystemArchitecture() );
504     return _val;
505   }
506
507   Arch ZConfig::systemArchitecture() const
508   { return _pimpl->cfg_arch; }
509
510   void ZConfig::setSystemArchitecture( const Arch & arch_r )
511   {
512     if ( arch_r != _pimpl->cfg_arch )
513     {
514       WAR << "Overriding system architecture (" << _pimpl->cfg_arch << "): " << arch_r << endl;
515       _pimpl->cfg_arch = arch_r;
516     }
517   }
518
519   ///////////////////////////////////////////////////////////////////
520   //
521   // text locale
522   //
523   ///////////////////////////////////////////////////////////////////
524
525   Locale ZConfig::defaultTextLocale()
526   {
527     static Locale _val( _autodetectTextLocale() );
528     return _val;
529   }
530
531   Locale ZConfig::textLocale() const
532   { return _pimpl->cfg_textLocale; }
533
534   void ZConfig::setTextLocale( const Locale & locale_r )
535   {
536     if ( locale_r != _pimpl->cfg_textLocale )
537     {
538       WAR << "Overriding text locale (" << _pimpl->cfg_textLocale << "): " << locale_r << endl;
539       _pimpl->cfg_textLocale = locale_r;
540     }
541   }
542
543   ///////////////////////////////////////////////////////////////////
544
545   Pathname ZConfig::repoCachePath() const
546   {
547     return ( _pimpl->cfg_cache_path.empty()
548         ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path );
549   }
550
551   Pathname ZConfig::repoMetadataPath() const
552   {
553     return ( _pimpl->cfg_metadata_path.empty()
554         ? (repoCachePath()/"raw") : _pimpl->cfg_metadata_path );
555   }
556
557   Pathname ZConfig::repoSolvfilesPath() const
558   {
559     return ( _pimpl->cfg_solvfiles_path.empty()
560         ? (repoCachePath()/"solv") : _pimpl->cfg_solvfiles_path );
561   }
562
563   Pathname ZConfig::repoPackagesPath() const
564   {
565     return ( _pimpl->cfg_packages_path.empty()
566         ? (repoCachePath()/"packages") : _pimpl->cfg_packages_path );
567   }
568
569   ///////////////////////////////////////////////////////////////////
570
571   Pathname ZConfig::configPath() const
572   {
573     return ( _pimpl->cfg_config_path.empty()
574         ? Pathname("/etc/zypp") : _pimpl->cfg_config_path );
575   }
576
577   Pathname ZConfig::knownReposPath() const
578   {
579     return ( _pimpl->cfg_known_repos_path.empty()
580         ? (configPath()/"repos.d") : _pimpl->cfg_known_repos_path );
581   }
582
583   Pathname ZConfig::knownServicesPath() const
584   {
585     return ( _pimpl->cfg_known_services_path.empty()
586         ? (configPath()/"services.d") : _pimpl->cfg_known_repos_path );
587   }
588
589   Pathname ZConfig::vendorPath() const
590   {
591     return ( _pimpl->cfg_vendor_path.empty()
592         ? (configPath()/"vendors.d") : _pimpl->cfg_vendor_path );
593   }
594
595   Pathname ZConfig::locksFile() const
596   {
597     return ( _pimpl->locks_file.empty()
598         ? (configPath()/"locks") : _pimpl->locks_file );
599   }
600
601   ///////////////////////////////////////////////////////////////////
602
603   bool ZConfig::repo_add_probe() const
604   {
605     return _pimpl->repo_add_probe;
606   }
607
608   unsigned ZConfig::repo_refresh_delay() const
609   {
610     return _pimpl->repo_refresh_delay;
611   }
612
613   bool ZConfig::download_use_deltarpm() const
614   { return _pimpl->download_use_deltarpm; }
615
616   bool ZConfig::download_use_deltarpm_always() const
617   { return download_use_deltarpm() && _pimpl->download_use_deltarpm_always; }
618
619   bool ZConfig::download_media_prefer_download() const
620   { return _pimpl->download_media_prefer_download.get(); }
621
622   void ZConfig::set_download_media_prefer_download( bool yesno_r )
623   { _pimpl->download_media_prefer_download.set( yesno_r ); }
624
625   void ZConfig::set_default_download_media_prefer_download()
626   { _pimpl->download_media_prefer_download.restoreToDefault(); }
627
628   long ZConfig::download_max_concurrent_connections() const
629   { return _pimpl->download_max_concurrent_connections; }
630
631   long ZConfig::download_min_download_speed() const
632   { return _pimpl->download_min_download_speed; }
633
634   long ZConfig::download_max_download_speed() const
635   { return _pimpl->download_max_download_speed; }
636
637   long ZConfig::download_max_silent_tries() const
638   { return _pimpl->download_max_silent_tries; }
639
640   bool ZConfig::solver_onlyRequires() const
641   { return _pimpl->solver_onlyRequires.get(); }
642
643   bool ZConfig::solver_allowVendorChange() const
644   { return _pimpl->solver_allowVendorChange.get(); }
645
646   Pathname ZConfig::solver_checkSystemFile() const
647   { return ( _pimpl->solver_checkSystemFile.empty()
648       ? (configPath()/"systemCheck") : _pimpl->solver_checkSystemFile ); }
649
650   std::set<IdString> ZConfig::multiversion() const
651   { return _pimpl->multiversion; }
652
653   void ZConfig::addMultiversion(std::string &name)
654   { _pimpl->multiversion.insert(IdString(name)); }
655
656   bool ZConfig::removeMultiversion(std::string &name)
657   { return _pimpl->multiversion.erase(IdString(name)); }
658
659   bool ZConfig::apply_locks_file() const
660   { return _pimpl->apply_locks_file; }
661
662   Pathname ZConfig::update_dataPath() const
663   {
664     return ( _pimpl->update_data_path.empty()
665         ? Pathname("/var/adm") : _pimpl->update_data_path );
666   }
667
668   Pathname ZConfig::update_messagesPath() const
669   {
670     return ( _pimpl->update_messages_path.empty()
671              ? Pathname(update_dataPath()/"update-messages") : _pimpl->update_messages_path );
672   }
673
674
675   Pathname ZConfig::update_scriptsPath() const
676   {
677     return ( _pimpl->update_scripts_path.empty()
678              ? Pathname(update_dataPath()/"update-scripts") : _pimpl->update_scripts_path );
679   }
680
681   ///////////////////////////////////////////////////////////////////
682
683   target::rpm::RpmInstFlags ZConfig::rpmInstallFlags() const
684   { return _pimpl->rpmInstallFlags; }
685
686
687   Pathname ZConfig::historyLogFile() const
688   {
689     return ( _pimpl->history_log_path.empty() ?
690         Pathname("/var/log/zypp/history") : _pimpl->history_log_path );
691   }
692
693
694   Pathname ZConfig::credentialsGlobalDir() const
695   {
696     return ( _pimpl->credentials_global_dir_path.empty() ?
697         Pathname("/etc/zypp/credentials.d") : _pimpl->credentials_global_dir_path );
698   }
699
700   Pathname ZConfig::credentialsGlobalFile() const
701   {
702     return ( _pimpl->credentials_global_file_path.empty() ?
703         Pathname("/etc/zypp/credentials.cat") : _pimpl->credentials_global_file_path );
704   }
705
706   ///////////////////////////////////////////////////////////////////
707
708   std::ostream & ZConfig::about( std::ostream & str ) const
709   {
710     str << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
711     str << "zypp.conf: '" << _pimpl->_parsedZyppConf << "'" << endl;
712     str << "TextLocale: '" << textLocale() << "' (" << defaultTextLocale() << ")" << endl;
713     str << "SystemArchitecture: '" << systemArchitecture() << "' (" << defaultSystemArchitecture() << ")" << endl;
714     return str;
715   }
716
717   /////////////////////////////////////////////////////////////////
718 } // namespace zypp
719 ///////////////////////////////////////////////////////////////////