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