Propagate ZConfig::setTextLocale to pool. (bnc#588850)
[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 #include <satsolver/satversion.h>
17 }
18 #include <iostream>
19 #include <fstream>
20 #include "zypp/base/Logger.h"
21 #include "zypp/base/IOStream.h"
22 #include "zypp/base/InputStream.h"
23 #include "zypp/base/String.h"
24
25 #include "zypp/ZConfig.h"
26 #include "zypp/ZYppFactory.h"
27 #include "zypp/PathInfo.h"
28 #include "zypp/parser/IniDict.h"
29
30 #include "zypp/sat/Pool.h"
31
32 using namespace std;
33 using namespace zypp::filesystem;
34 using namespace zypp::parser;
35
36 #undef ZYPP_BASE_LOGGER_LOGGROUP
37 #define ZYPP_BASE_LOGGER_LOGGROUP "zconfig"
38
39 ///////////////////////////////////////////////////////////////////
40 namespace zypp
41 { /////////////////////////////////////////////////////////////////
42
43   ///////////////////////////////////////////////////////////////////
44   namespace
45   { /////////////////////////////////////////////////////////////////
46
47     /** Determine system architecture evaluating \c uname and \c /proc/cpuinfo.
48     */
49     Arch _autodetectSystemArchitecture()
50     {
51       struct ::utsname buf;
52       if ( ::uname( &buf ) < 0 )
53       {
54         ERR << "Can't determine system architecture" << endl;
55         return Arch_noarch;
56       }
57
58       Arch architecture( buf.machine );
59       MIL << "Uname architecture is '" << buf.machine << "'" << endl;
60
61       // some CPUs report i686 but dont implement cx8 and cmov
62       // check for both flags in /proc/cpuinfo and downgrade
63       // to i586 if either is missing (cf bug #18885)
64       if ( architecture == Arch_i686 )
65       {
66         std::ifstream cpuinfo( "/proc/cpuinfo" );
67         if ( cpuinfo )
68         {
69           for( iostr::EachLine in( cpuinfo ); in; in.next() )
70           {
71             if ( str::hasPrefix( *in, "flags" ) )
72             {
73               if (    in->find( "cx8" ) == std::string::npos
74                    || in->find( "cmov" ) == std::string::npos )
75               {
76                 architecture = Arch_i586;
77                 WAR << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
78               }
79               break;
80             }
81           }
82         }
83         else
84         {
85           ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl;
86         }
87       }
88       return architecture;
89     }
90
91      /** The locale to be used for texts and messages.
92      *
93      * For the encoding to be used the preference is
94      *
95      *    LC_ALL, LC_CTYPE, LANG
96      *
97      * For the language of the messages to be used, the preference is
98      *
99      *    LANGUAGE, LC_ALL, LC_MESSAGES, LANG
100      *
101      * Note that LANGUAGE can contain more than one locale name, it can be
102      * a list of locale names like for example
103      *
104      *    LANGUAGE=ja_JP.UTF-8:de_DE.UTF-8:fr_FR.UTF-8
105
106      * \todo Support dynamic fallbacklists defined by LANGUAGE
107      */
108     Locale _autodetectTextLocale()
109     {
110       Locale ret( "en" );
111       const char * envlist[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL };
112       for ( const char ** envvar = envlist; *envvar; ++envvar )
113       {
114         const char * envlang = getenv( *envvar );
115         if ( envlang )
116         {
117           std::string envstr( envlang );
118           if ( envstr != "POSIX" && envstr != "C" )
119           {
120             Locale lang( envstr );
121             if ( ! lang.code().empty() )
122             {
123               MIL << "Found " << *envvar << "=" << envstr << endl;
124               ret = lang;
125               break;
126             }
127           }
128         }
129       }
130       MIL << "Default text locale is '" << ret << "'" << endl;
131 #warning HACK AROUND BOOST_TEST_CATCH_SYSTEM_ERRORS
132       setenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS", "no", 1 );
133       return ret;
134     }
135
136    /////////////////////////////////////////////////////////////////
137   } // namespace zypp
138   ///////////////////////////////////////////////////////////////////
139
140   /** Mutable option. */
141   template<class _Tp>
142       struct Option
143       {
144         typedef _Tp value_type;
145
146         /** No default ctor, explicit initialisation! */
147         Option( const value_type & initial_r )
148           : _val( initial_r )
149         {}
150
151         /** Get the value.  */
152         const value_type & get() const
153         { return _val; }
154
155         /** Autoconversion to value_type.  */
156         operator const value_type &() const
157         { return _val; }
158
159         /** Set a new value.  */
160         void set( const value_type & newval_r )
161         { _val = newval_r; }
162
163         /** Non-const reference to set a new value. */
164         value_type & ref()
165         { return _val; }
166
167         private:
168           value_type _val;
169       };
170
171   /** Mutable option with initial value also remembering a config value. */
172   template<class _Tp>
173       struct DefaultOption : public Option<_Tp>
174       {
175         typedef _Tp         value_type;
176         typedef Option<_Tp> option_type;
177
178         DefaultOption( const value_type & initial_r )
179           : Option<_Tp>( initial_r ), _default( initial_r )
180         {}
181
182         /** Reset value to the current default. */
183         void restoreToDefault()
184         { this->set( _default.get() ); }
185
186         /** Reset value to a new default. */
187         void restoreToDefault( const value_type & newval_r )
188         { setDefault( newval_r ); restoreToDefault(); }
189
190         /** Get the current default value. */
191         const value_type & getDefault() const
192         { return _default.get(); }
193
194         /** Set a new default value. */
195         void setDefault( const value_type & newval_r )
196         { _default.set( newval_r ); }
197
198         private:
199           option_type _default;
200       };
201
202   ///////////////////////////////////////////////////////////////////
203   //
204   //    CLASS NAME : ZConfig::Impl
205   //
206   /** ZConfig implementation.
207    * \todo Enrich section and entry definition by some comment
208    * (including the default setting and provide some method to
209    * write this into a sample zypp.conf.
210   */
211   class ZConfig::Impl
212   {
213     public:
214       Impl( const Pathname & override_r = Pathname() )
215         : _parsedZyppConf               ( override_r )
216         , cfg_arch                      ( defaultSystemArchitecture() )
217         , cfg_textLocale                ( defaultTextLocale() )
218         , updateMessagesNotify          ( "single | /usr/lib/zypp/notify-message -p %p" )
219         , repo_add_probe                ( false )
220         , repo_refresh_delay            ( 10 )
221         , repoLabelIsAlias              ( false )
222         , download_use_deltarpm         ( true )
223         , download_use_deltarpm_always  ( false )
224         , download_media_prefer_download( true )
225         , download_max_concurrent_connections( 2 )
226         , download_min_download_speed   ( 0 )
227         , download_max_download_speed   ( 0 )
228         , download_max_silent_tries     ( 5 )
229         , commit_downloadMode           ( DownloadDefault )
230         , solver_onlyRequires           ( false )
231         , solver_allowVendorChange      ( false )
232         , solver_upgradeTestcasesToKeep ( 2 )
233         , solverUpgradeRemoveDroppedPackages( true )
234         , apply_locks_file              ( true )
235
236       {
237         MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
238         // override_r has higest prio
239         // ZYPP_CONF might override /etc/zypp/zypp.conf
240         if ( _parsedZyppConf.empty() )
241         {
242           const char *env_confpath = getenv( "ZYPP_CONF" );
243           _parsedZyppConf = env_confpath ? env_confpath : "/etc/zypp/zypp.conf";
244         }
245         else
246         {
247           // Inject this into ZConfig. Be shure this is
248           // allocated via new. See: reconfigureZConfig
249           INT << "Reconfigure to " << _parsedZyppConf << endl;
250           ZConfig::instance()._pimpl.reset( this );
251         }
252         if ( PathInfo(_parsedZyppConf).isExist() )
253         {
254           parser::IniDict dict( _parsedZyppConf );
255           for ( IniDict::section_const_iterator sit = dict.sectionsBegin();
256                 sit != dict.sectionsEnd();
257                 ++sit )
258           {
259             string section(*sit);
260             //MIL << section << endl;
261             for ( IniDict::entry_const_iterator it = dict.entriesBegin(*sit);
262                   it != dict.entriesEnd(*sit);
263                   ++it )
264             {
265               string entry(it->first);
266               string value(it->second);
267               //DBG << (*it).first << "=" << (*it).second << endl;
268               if ( section == "main" )
269               {
270                 if ( entry == "arch" )
271                 {
272                   Arch carch( value );
273                   if ( carch != cfg_arch )
274                   {
275                     WAR << "Overriding system architecture (" << cfg_arch << "): " << carch << endl;
276                     cfg_arch = carch;
277                   }
278                 }
279                 else if ( entry == "cachedir" )
280                 {
281                   cfg_cache_path = Pathname(value);
282                 }
283                 else if ( entry == "metadatadir" )
284                 {
285                   cfg_metadata_path = Pathname(value);
286                 }
287                 else if ( entry == "solvfilesdir" )
288                 {
289                   cfg_solvfiles_path = Pathname(value);
290                 }
291                 else if ( entry == "packagesdir" )
292                 {
293                   cfg_packages_path = Pathname(value);
294                 }
295                 else if ( entry == "configdir" )
296                 {
297                   cfg_config_path = Pathname(value);
298                 }
299                 else if ( entry == "reposdir" )
300                 {
301                   cfg_known_repos_path = Pathname(value);
302                 }
303                 else if ( entry == "servicesdir" )
304                 {
305                   cfg_known_services_path = Pathname(value);
306                 }
307                 else if ( entry == "repo.add.probe" )
308                 {
309                   repo_add_probe = str::strToBool( value, repo_add_probe );
310                 }
311                 else if ( entry == "repo.refresh.delay" )
312                 {
313                   str::strtonum(value, repo_refresh_delay);
314                 }
315                 else if ( entry == "download.use_deltarpm" )
316                 {
317                   download_use_deltarpm = str::strToBool( value, download_use_deltarpm );
318                 }
319                 else if ( entry == "download.use_deltarpm.always" )
320                 {
321                   download_use_deltarpm_always = str::strToBool( value, download_use_deltarpm_always );
322                 }
323                 else if ( entry == "download.media_preference" )
324                 {
325                   download_media_prefer_download.restoreToDefault( str::compareCI( value, "volatile" ) != 0 );
326                 }
327                 else if ( entry == "download.max_concurrent_connections" )
328                 {
329                   str::strtonum(value, download_max_concurrent_connections);
330                 }
331                 else if ( entry == "download.min_download_speed" )
332                 {
333                   str::strtonum(value, download_min_download_speed);
334                 }
335                 else if ( entry == "download.max_download_speed" )
336                 {
337                   str::strtonum(value, download_max_download_speed);
338                 }
339                 else if ( entry == "download.max_silent_tries" )
340                 {
341                   str::strtonum(value, download_max_silent_tries);
342                 }
343                 else if ( entry == "commit.downloadMode" )
344                 {
345                   commit_downloadMode.set( deserializeDownloadMode( value ) );
346                 }
347                 else if ( entry == "vendordir" )
348                 {
349                   cfg_vendor_path = Pathname(value);
350                 }
351                 else if ( entry == "solver.onlyRequires" )
352                 {
353                   solver_onlyRequires.set( str::strToBool( value, solver_onlyRequires ) );
354                 }
355                 else if ( entry == "solver.allowVendorChange" )
356                 {
357                   solver_allowVendorChange.set( str::strToBool( value, solver_allowVendorChange ) );
358                 }
359                 else if ( entry == "solver.upgradeTestcasesToKeep" )
360                 {
361                   solver_upgradeTestcasesToKeep.set( str::strtonum<unsigned>( value ) );
362                 }
363                 else if ( entry == "solver.upgradeRemoveDroppedPackages" )
364                 {
365                   solverUpgradeRemoveDroppedPackages.restoreToDefault( str::strToBool( value, solverUpgradeRemoveDroppedPackages.getDefault() ) );
366                 }
367                 else if ( entry == "solver.checkSystemFile" )
368                 {
369                   solver_checkSystemFile = Pathname(value);
370                 }
371                 else if ( entry == "multiversion" )
372                 {
373                   str::split( value, inserter( multiversion, multiversion.end() ), ", \t" );
374                 }
375                 else if ( entry == "locksfile.path" )
376                 {
377                   locks_file = Pathname(value);
378                 }
379                 else if ( entry == "locksfile.apply" )
380                 {
381                   apply_locks_file = str::strToBool( value, apply_locks_file );
382                 }
383                 else if ( entry == "update.datadir" )
384                 {
385                   update_data_path = Pathname(value);
386                 }
387                 else if ( entry == "update.scriptsdir" )
388                 {
389                   update_scripts_path = Pathname(value);
390                 }
391                 else if ( entry == "update.messagessdir" )
392                 {
393                   update_messages_path = Pathname(value);
394                 }
395                 else if ( entry == "update.messages.notify" )
396                 {
397                   updateMessagesNotify.set( value );
398                 }
399                 else if ( entry == "rpm.install.excludedocs" )
400                 {
401                   rpmInstallFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS,
402                                            str::strToBool( value, false ) );
403                 }
404                 else if ( entry == "history.logfile" )
405                 {
406                   history_log_path = Pathname(value);
407                 }
408                 else if ( entry == "credentials.global.dir" )
409                 {
410                   credentials_global_dir_path = Pathname(value);
411                 }
412                 else if ( entry == "credentials.global.file" )
413                 {
414                   credentials_global_file_path = Pathname(value);
415                 }
416               }
417             }
418           }
419         }
420         else
421         {
422           MIL << _parsedZyppConf << " not found, using defaults instead." << endl;
423           _parsedZyppConf = _parsedZyppConf.extend( " (NOT FOUND)" );
424         }
425
426         // legacy:
427         if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
428         {
429           Arch carch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
430           if ( carch != cfg_arch )
431           {
432             WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Overriding system architecture (" << cfg_arch << "): " << carch << endl;
433             cfg_arch = carch;
434           }
435         }
436         MIL << "ZConfig singleton created." << endl;
437       }
438
439       ~Impl()
440       {}
441
442     public:
443     /** Remember any parsed zypp.conf. */
444     Pathname _parsedZyppConf;
445
446     Arch     cfg_arch;
447     Locale   cfg_textLocale;
448
449     Pathname cfg_cache_path;
450     Pathname cfg_metadata_path;
451     Pathname cfg_solvfiles_path;
452     Pathname cfg_packages_path;
453
454     Pathname cfg_config_path;
455     Pathname cfg_known_repos_path;
456     Pathname cfg_known_services_path;
457     Pathname cfg_vendor_path;
458     Pathname locks_file;
459
460     Pathname update_data_path;
461     Pathname update_scripts_path;
462     Pathname update_messages_path;
463     DefaultOption<std::string> updateMessagesNotify;
464
465     bool repo_add_probe;
466     unsigned repo_refresh_delay;
467     bool repoLabelIsAlias;
468
469     bool download_use_deltarpm;
470     bool download_use_deltarpm_always;
471     DefaultOption<bool> download_media_prefer_download;
472
473     int download_max_concurrent_connections;
474     int download_min_download_speed;
475     int download_max_download_speed;
476     int download_max_silent_tries;
477
478     Option<DownloadMode> commit_downloadMode;
479
480     Option<bool>        solver_onlyRequires;
481     Option<bool>        solver_allowVendorChange;
482     Option<unsigned>    solver_upgradeTestcasesToKeep;
483     DefaultOption<bool> solverUpgradeRemoveDroppedPackages;
484
485     Pathname solver_checkSystemFile;
486
487     std::set<std::string> multiversion;
488
489     bool apply_locks_file;
490
491     target::rpm::RpmInstFlags rpmInstallFlags;
492
493     Pathname history_log_path;
494     Pathname credentials_global_dir_path;
495     Pathname credentials_global_file_path;
496   };
497   ///////////////////////////////////////////////////////////////////
498
499   // Backdoor to redirect ZConfig from within the running
500   // TEST-application. HANDLE WITH CARE!
501   void reconfigureZConfig( const Pathname & override_r )
502   {
503     // ctor puts itself unter smart pointer control.
504     new ZConfig::Impl( override_r );
505   }
506
507   ///////////////////////////////////////////////////////////////////
508   //
509   //    METHOD NAME : ZConfig::instance
510   //    METHOD TYPE : ZConfig &
511   //
512   ZConfig & ZConfig::instance()
513   {
514     static ZConfig _instance; // The singleton
515     return _instance;
516   }
517
518   ///////////////////////////////////////////////////////////////////
519   //
520   //    METHOD NAME : ZConfig::ZConfig
521   //    METHOD TYPE : Ctor
522   //
523   ZConfig::ZConfig()
524   : _pimpl( new Impl )
525   {
526     about( MIL );
527   }
528
529   ///////////////////////////////////////////////////////////////////
530   //
531   //    METHOD NAME : ZConfig::~ZConfig
532   //    METHOD TYPE : Dtor
533   //
534   ZConfig::~ZConfig( )
535   {}
536
537   Pathname ZConfig::systemRoot() const
538   {
539     Target_Ptr target( getZYpp()->getTarget() );
540     return target ? target->root() : Pathname();
541   }
542
543   ///////////////////////////////////////////////////////////////////
544   //
545   // system architecture
546   //
547   ///////////////////////////////////////////////////////////////////
548
549   Arch ZConfig::defaultSystemArchitecture()
550   {
551     static Arch _val( _autodetectSystemArchitecture() );
552     return _val;
553   }
554
555   Arch ZConfig::systemArchitecture() const
556   { return _pimpl->cfg_arch; }
557
558   void ZConfig::setSystemArchitecture( const Arch & arch_r )
559   {
560     if ( arch_r != _pimpl->cfg_arch )
561     {
562       WAR << "Overriding system architecture (" << _pimpl->cfg_arch << "): " << arch_r << endl;
563       _pimpl->cfg_arch = arch_r;
564     }
565   }
566
567   ///////////////////////////////////////////////////////////////////
568   //
569   // text locale
570   //
571   ///////////////////////////////////////////////////////////////////
572
573   Locale ZConfig::defaultTextLocale()
574   {
575     static Locale _val( _autodetectTextLocale() );
576     return _val;
577   }
578
579   Locale ZConfig::textLocale() const
580   { return _pimpl->cfg_textLocale; }
581
582   void ZConfig::setTextLocale( const Locale & locale_r )
583   {
584     if ( locale_r != _pimpl->cfg_textLocale )
585     {
586       WAR << "Overriding text locale (" << _pimpl->cfg_textLocale << "): " << locale_r << endl;
587       _pimpl->cfg_textLocale = locale_r;
588 #warning prefer signal
589       sat::Pool::instance().setTextLocale( locale_r );
590     }
591   }
592
593   ///////////////////////////////////////////////////////////////////
594
595   Pathname ZConfig::repoCachePath() const
596   {
597     return ( _pimpl->cfg_cache_path.empty()
598         ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path );
599   }
600
601   Pathname ZConfig::repoMetadataPath() const
602   {
603     return ( _pimpl->cfg_metadata_path.empty()
604         ? (repoCachePath()/"raw") : _pimpl->cfg_metadata_path );
605   }
606
607   Pathname ZConfig::repoSolvfilesPath() const
608   {
609     return ( _pimpl->cfg_solvfiles_path.empty()
610         ? (repoCachePath()/"solv") : _pimpl->cfg_solvfiles_path );
611   }
612
613   Pathname ZConfig::repoPackagesPath() const
614   {
615     return ( _pimpl->cfg_packages_path.empty()
616         ? (repoCachePath()/"packages") : _pimpl->cfg_packages_path );
617   }
618
619   ///////////////////////////////////////////////////////////////////
620
621   Pathname ZConfig::configPath() const
622   {
623     return ( _pimpl->cfg_config_path.empty()
624         ? Pathname("/etc/zypp") : _pimpl->cfg_config_path );
625   }
626
627   Pathname ZConfig::knownReposPath() const
628   {
629     return ( _pimpl->cfg_known_repos_path.empty()
630         ? (configPath()/"repos.d") : _pimpl->cfg_known_repos_path );
631   }
632
633   Pathname ZConfig::knownServicesPath() const
634   {
635     return ( _pimpl->cfg_known_services_path.empty()
636         ? (configPath()/"services.d") : _pimpl->cfg_known_repos_path );
637   }
638
639   Pathname ZConfig::vendorPath() const
640   {
641     return ( _pimpl->cfg_vendor_path.empty()
642         ? (configPath()/"vendors.d") : _pimpl->cfg_vendor_path );
643   }
644
645   Pathname ZConfig::locksFile() const
646   {
647     return ( _pimpl->locks_file.empty()
648         ? (configPath()/"locks") : _pimpl->locks_file );
649   }
650
651   ///////////////////////////////////////////////////////////////////
652
653   bool ZConfig::repo_add_probe() const
654   {
655     return _pimpl->repo_add_probe;
656   }
657
658   unsigned ZConfig::repo_refresh_delay() const
659   {
660     return _pimpl->repo_refresh_delay;
661   }
662
663   bool ZConfig::repoLabelIsAlias() const
664   { return _pimpl->repoLabelIsAlias; }
665
666   void ZConfig::repoLabelIsAlias( bool yesno_r )
667   { _pimpl->repoLabelIsAlias = yesno_r; }
668
669   bool ZConfig::download_use_deltarpm() const
670   { return _pimpl->download_use_deltarpm; }
671
672   bool ZConfig::download_use_deltarpm_always() const
673   { return download_use_deltarpm() && _pimpl->download_use_deltarpm_always; }
674
675   bool ZConfig::download_media_prefer_download() const
676   { return _pimpl->download_media_prefer_download; }
677
678   void ZConfig::set_download_media_prefer_download( bool yesno_r )
679   { _pimpl->download_media_prefer_download.set( yesno_r ); }
680
681   void ZConfig::set_default_download_media_prefer_download()
682   { _pimpl->download_media_prefer_download.restoreToDefault(); }
683
684   long ZConfig::download_max_concurrent_connections() const
685   { return _pimpl->download_max_concurrent_connections; }
686
687   long ZConfig::download_min_download_speed() const
688   { return _pimpl->download_min_download_speed; }
689
690   long ZConfig::download_max_download_speed() const
691   { return _pimpl->download_max_download_speed; }
692
693   long ZConfig::download_max_silent_tries() const
694   { return _pimpl->download_max_silent_tries; }
695
696   DownloadMode ZConfig::commit_downloadMode() const
697   { return _pimpl->commit_downloadMode; }
698
699   bool ZConfig::solver_onlyRequires() const
700   { return _pimpl->solver_onlyRequires; }
701
702   bool ZConfig::solver_allowVendorChange() const
703   { return _pimpl->solver_allowVendorChange; }
704
705   Pathname ZConfig::solver_checkSystemFile() const
706   { return ( _pimpl->solver_checkSystemFile.empty()
707       ? (configPath()/"systemCheck") : _pimpl->solver_checkSystemFile ); }
708
709   unsigned ZConfig::solver_upgradeTestcasesToKeep() const
710   { return _pimpl->solver_upgradeTestcasesToKeep; }
711
712   bool ZConfig::solverUpgradeRemoveDroppedPackages() const              { return _pimpl->solverUpgradeRemoveDroppedPackages; }
713   void ZConfig::setSolverUpgradeRemoveDroppedPackages( bool val_r )     { _pimpl->solverUpgradeRemoveDroppedPackages.set( val_r ); }
714   void ZConfig::resetSolverUpgradeRemoveDroppedPackages()               { _pimpl->solverUpgradeRemoveDroppedPackages.restoreToDefault(); }
715
716   const std::set<std::string> & ZConfig::multiversionSpec() const       { return _pimpl->multiversion; }
717   void ZConfig::addMultiversionSpec( const std::string & name_r )       { _pimpl->multiversion.insert( name_r ); }
718   void ZConfig::removeMultiversionSpec( const std::string & name_r )    { _pimpl->multiversion.erase( name_r ); }
719
720   bool ZConfig::apply_locks_file() const
721   { return _pimpl->apply_locks_file; }
722
723   Pathname ZConfig::update_dataPath() const
724   {
725     return ( _pimpl->update_data_path.empty()
726         ? Pathname("/var/adm") : _pimpl->update_data_path );
727   }
728
729   Pathname ZConfig::update_messagesPath() const
730   {
731     return ( _pimpl->update_messages_path.empty()
732              ? Pathname(update_dataPath()/"update-messages") : _pimpl->update_messages_path );
733   }
734
735   Pathname ZConfig::update_scriptsPath() const
736   {
737     return ( _pimpl->update_scripts_path.empty()
738              ? Pathname(update_dataPath()/"update-scripts") : _pimpl->update_scripts_path );
739   }
740
741   std::string ZConfig::updateMessagesNotify() const
742   { return _pimpl->updateMessagesNotify; }
743
744   void ZConfig::setUpdateMessagesNotify( const std::string & val_r )
745   { _pimpl->updateMessagesNotify.set( val_r ); }
746
747   void ZConfig::resetUpdateMessagesNotify()
748   { _pimpl->updateMessagesNotify.restoreToDefault(); }
749
750   ///////////////////////////////////////////////////////////////////
751
752   target::rpm::RpmInstFlags ZConfig::rpmInstallFlags() const
753   { return _pimpl->rpmInstallFlags; }
754
755
756   Pathname ZConfig::historyLogFile() const
757   {
758     return ( _pimpl->history_log_path.empty() ?
759         Pathname("/var/log/zypp/history") : _pimpl->history_log_path );
760   }
761
762
763   Pathname ZConfig::credentialsGlobalDir() const
764   {
765     return ( _pimpl->credentials_global_dir_path.empty() ?
766         Pathname("/etc/zypp/credentials.d") : _pimpl->credentials_global_dir_path );
767   }
768
769   Pathname ZConfig::credentialsGlobalFile() const
770   {
771     return ( _pimpl->credentials_global_file_path.empty() ?
772         Pathname("/etc/zypp/credentials.cat") : _pimpl->credentials_global_file_path );
773   }
774
775   ///////////////////////////////////////////////////////////////////
776
777   std::string ZConfig::distroverpkg() const
778   { return "redhat-release"; }
779
780   ///////////////////////////////////////////////////////////////////
781
782   std::ostream & ZConfig::about( std::ostream & str ) const
783   {
784     str << "libzypp: " << VERSION << " built " << __DATE__ << " " <<  __TIME__ << endl;
785
786     str << "satsolver: " << sat_version;
787     if ( ::strcmp( sat_version, SATSOLVER_VERSION_STRING ) )
788       str << " (built against " << SATSOLVER_VERSION_STRING << ")";
789     str << endl;
790
791     str << "zypp.conf: '" << _pimpl->_parsedZyppConf << "'" << endl;
792     str << "TextLocale: '" << textLocale() << "' (" << defaultTextLocale() << ")" << endl;
793     str << "SystemArchitecture: '" << systemArchitecture() << "' (" << defaultSystemArchitecture() << ")" << endl;
794     return str;
795   }
796
797   /////////////////////////////////////////////////////////////////
798 } // namespace zypp
799 ///////////////////////////////////////////////////////////////////