1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/zypp_detail/ZYppImpl.cc
13 #include <sys/utsname.h>
17 #include "zypp/base/Logger.h"
18 #include "zypp/base/String.h"
20 #include "zypp/zypp_detail/ZYppImpl.h"
21 #include "zypp/detail/ResImplTraits.h"
22 #include "zypp/solver/detail/Helper.h"
23 #include "zypp/target/TargetImpl.h"
24 #include "zypp/ZYpp.h"
25 #include "zypp/NVRAD.h"
26 #include "zypp/Language.h"
27 #include "zypp/DiskUsageCounter.h"
28 #include "zypp/NameKindProxy.h"
32 ///////////////////////////////////////////////////////////////////
34 { /////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////
37 { /////////////////////////////////////////////////////////////////
39 inline Locale defaultTextLocale()
42 const char * envlist[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
43 for ( const char ** envvar = envlist; *envvar; ++envvar )
45 const char * envlang = getenv( *envvar );
48 std::string envstr( envlang );
49 if ( envstr != "POSIX" && envstr != "C" )
51 Locale lang( envlang );
52 if ( lang != Locale::noCode )
63 Arch defaultArchitecture()
67 // detect the true architecture
69 if ( uname( &buf ) < 0 )
71 ERR << "Can't determine system architecture" << endl;
75 architecture = Arch( buf.machine );
76 DBG << "uname architecture is '" << buf.machine << "'" << endl;
78 // some CPUs report i686 but dont implement cx8 and cmov
79 // check for both flags in /proc/cpuinfo and downgrade
80 // to i586 if either is missing (cf bug #18885)
82 if ( architecture == Arch_i686 )
84 std::ifstream cpuinfo( "/proc/cpuinfo" );
87 ERR << "Cant open /proc/cpuinfo" << endl;
92 while ( cpuinfo.good() )
94 if ( !cpuinfo.getline( infoline, 1024, '\n' ) )
99 if ( strncmp( infoline, "flags", 5 ) == 0 )
101 std::string flagsline( infoline );
102 if ( flagsline.find( "cx8" ) == std::string::npos
103 || flagsline.find( "cmov" ) == std::string::npos )
105 architecture = Arch_i586;
106 DBG << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
110 } // read proc/cpuinfo
111 } // proc/cpuinfo opened
112 } // i686 extra flags check
115 if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
117 architecture = Arch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
118 WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Setting fake system architecture for test purpuses to: '" << architecture << "'" << endl;
123 ///////////////////////////////////////////////////////////////////
125 // METHOD NAME : ZYppImpl::ZYppImpl
126 // METHOD TYPE : Constructor
129 : _textLocale( defaultTextLocale() )
132 , _resolver( new Resolver(_pool.accessor()) )
133 , _architecture( defaultArchitecture() )
136 MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " << __TIME__ << endl;
137 MIL << "defaultTextLocale: '" << _textLocale << "'" << endl;
138 MIL << "System architecture is '" << _architecture << "'" << endl;
140 MIL << "initializing keyring..." << std::endl;
141 //_keyring = new KeyRing(homePath() + Pathname("/keyring/all"), homePath() + Pathname("/keyring/trusted"));
142 _keyring = new KeyRing(tmpPath());
145 ///////////////////////////////////////////////////////////////////
147 // METHOD NAME : ZYppImpl::~ZYppImpl
148 // METHOD TYPE : Destructor
150 ZYppImpl::~ZYppImpl()
153 //------------------------------------------------------------------------
154 // add/remove resolvables
156 void ZYppImpl::addResolvables (const ResStore& store, bool installed)
158 _pool.insert(store.begin(), store.end(), installed);
161 void ZYppImpl::removeResolvables (const ResStore& store)
163 for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
169 void ZYppImpl::removeInstalledResolvables ()
171 for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
173 ResPool::const_iterator next = it; ++next;
174 if (it->status().isInstalled())
180 DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
181 { return _disk_usage.disk_usage(pool()); }
183 void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
184 { _disk_usage.setMountPoints(mp); }
186 DiskUsageCounter::MountPointSet ZYppImpl::getPartitions() const
187 { return _disk_usage.getMountPoints(); }
189 //------------------------------------------------------------------------
192 Target_Ptr ZYppImpl::target() const
195 ZYPP_THROW(Exception("Target not initialized."));
199 void ZYppImpl::initializeTarget(const Pathname & root)
201 MIL << "initTarget( " << root << endl;
203 if (_target->root() == root) {
204 MIL << "Repeated call to initializeTarget()" << endl;
207 removeInstalledResolvables( );
209 _target = new Target( root );
210 _target->enableStorage( root );
213 void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
215 MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
217 if (_target->root() == root) {
218 MIL << "Repeated call to initTarget()" << endl;
221 removeInstalledResolvables( );
223 _target = new Target( root );
224 _target->enableStorage( root );
227 addResolvables( _target->resolvables(), true );
232 void ZYppImpl::finishTarget()
235 removeInstalledResolvables();
239 //------------------------------------------------------------------------
242 /** \todo Remove workflow from target, lot's of it could be done here,
243 * and target used for transact. */
244 ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
246 if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
248 ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
251 MIL << "Attempt to commit (" << policy_r << ")" << endl;
253 ZYPP_THROW( Exception("Target not initialized.") );
255 ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
257 if (! policy_r.dryRun() ) {
258 // Tag target data invalid, so they are reloaded on the next call to
259 // target->resolvables(). Actually the target should do this without
262 removeInstalledResolvables();
263 if ( policy_r.syncPoolAfterCommit() )
265 // reload new status from target
266 addResolvables( _target->resolvables(), true );
270 MIL << "Commit (" << policy_r << ") returned: "
276 //------------------------------------------------------------------------
280 void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
282 ResPool mpool( pool() );
283 // assert all requested are available
284 for ( LocaleSet::const_iterator it = locales_r.begin();
285 it != locales_r.end(); ++it )
287 NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
288 if ( select.installedEmpty() && select.availableEmpty() )
289 _pool.insert( Language::availableInstance( *it ) );
293 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
294 it != mpool.byKindEnd<Language>(); ++it )
296 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
297 if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
299 // Language is requested
300 if ( select.installedEmpty() )
302 if ( select.availableEmpty() )
304 // no item ==> provide available to install
305 _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
306 select = nameKindProxy<Language>( mpool, (*it)->name() );
308 // available only ==> to install
309 select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
313 // installed ==> keep it
314 select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
315 if ( ! select.availableEmpty() )
317 // both items ==> keep
318 select.availableBegin()->status().resetTransact( ResStatus::USER );
324 // Language is NOT requested
325 if ( ! select.installedEmpty() )
326 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
327 if ( ! select.availableEmpty() )
328 select.availableBegin()->status().resetTransact( ResStatus::USER );
334 ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
337 ResPool mpool( pool() );
338 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
339 it != mpool.byKindEnd<Language>(); ++it )
341 if ( (*it).status().isUninstalled() ) // available!
342 ret.insert( Locale( (*it)->name() ) );
348 ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
351 ResPool mpool( pool() );
352 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
353 it != mpool.byKindEnd<Language>(); ++it )
355 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
356 if ( ! select.installedEmpty()
357 && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
358 ret.insert( Locale( (*it)->name() ) );
359 else if ( ! select.availableEmpty()
360 && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
361 ret.insert( Locale( (*it)->name() ) );
366 void ZYppImpl::availableLocale( const Locale & locale_r )
368 _pool.insert( Language::availableInstance( locale_r ) );
371 //------------------------------------------------------------------------
374 void ZYppImpl::setArchitecture( const Arch & arch )
376 _architecture = arch;
377 if (_resolver) _resolver->setArchitecture( arch );
380 //------------------------------------------------------------------------
383 Pathname ZYppImpl::homePath() const
384 { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
386 void ZYppImpl::setHomePath( const Pathname & path )
387 { _home_path = path; }
389 Pathname ZYppImpl::tmpPath() const
391 static TmpDir zypp_tmp_dir("/var/tmp", "zypp.");
392 return zypp_tmp_dir.path();
395 /******************************************************************
397 ** FUNCTION NAME : operator<<
398 ** FUNCTION TYPE : std::ostream &
400 std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
402 return str << "ZYppImpl";
405 /////////////////////////////////////////////////////////////////
406 } // namespace zypp_detail
407 ///////////////////////////////////////////////////////////////////
408 /////////////////////////////////////////////////////////////////
410 ///////////////////////////////////////////////////////////////////