1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/zypp_detail/ZYppImpl.cc
13 #include <sys/utsname.h>
17 #include "zypp/TmpPath.h"
18 #include "zypp/base/Logger.h"
19 #include "zypp/base/String.h"
21 #include "zypp/zypp_detail/ZYppImpl.h"
22 #include "zypp/detail/ResImplTraits.h"
23 #include "zypp/solver/detail/Helper.h"
24 #include "zypp/target/TargetImpl.h"
25 #include "zypp/ZYpp.h"
26 #include "zypp/NVRAD.h"
27 #include "zypp/Language.h"
28 #include "zypp/DiskUsageCounter.h"
29 #include "zypp/NameKindProxy.h"
30 #include "zypp/Locks.h"
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////
39 { /////////////////////////////////////////////////////////////////
41 inline Locale defaultTextLocale()
44 const char * envlist[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
45 for ( const char ** envvar = envlist; *envvar; ++envvar )
47 const char * envlang = getenv( *envvar );
50 std::string envstr( envlang );
51 if ( envstr != "POSIX" && envstr != "C" )
53 Locale lang( envlang );
54 if ( ! lang.code().empty() )
65 Arch defaultArchitecture()
69 // detect the true architecture
71 if ( uname( &buf ) < 0 )
73 ERR << "Can't determine system architecture" << endl;
77 architecture = Arch( buf.machine );
78 DBG << "uname architecture is '" << buf.machine << "'" << endl;
80 // some CPUs report i686 but dont implement cx8 and cmov
81 // check for both flags in /proc/cpuinfo and downgrade
82 // to i586 if either is missing (cf bug #18885)
84 if ( architecture == Arch_i686 )
86 std::ifstream cpuinfo( "/proc/cpuinfo" );
89 ERR << "Cant open /proc/cpuinfo" << endl;
94 while ( cpuinfo.good() )
96 if ( !cpuinfo.getline( infoline, 1024, '\n' ) )
101 if ( strncmp( infoline, "flags", 5 ) == 0 )
103 std::string flagsline( infoline );
104 if ( flagsline.find( "cx8" ) == std::string::npos
105 || flagsline.find( "cmov" ) == std::string::npos )
107 architecture = Arch_i586;
108 DBG << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
112 } // read proc/cpuinfo
113 } // proc/cpuinfo opened
114 } // i686 extra flags check
117 if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
119 architecture = Arch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
120 WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Setting fake system architecture for test purpuses to: '" << architecture << "'" << endl;
125 ///////////////////////////////////////////////////////////////////
127 // METHOD NAME : ZYppImpl::ZYppImpl
128 // METHOD TYPE : Constructor
131 : _textLocale( defaultTextLocale() )
134 , _resolver( new Resolver(_pool.accessor()) )
135 , _architecture( defaultArchitecture() )
137 MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " << __TIME__ << endl;
138 MIL << "defaultTextLocale: '" << _textLocale << "'" << endl;
139 MIL << "System architecture is '" << _architecture << "'" << endl;
141 MIL << "initializing keyring..." << std::endl;
142 //_keyring = new KeyRing(homePath() + Pathname("/keyring/all"), homePath() + Pathname("/keyring/trusted"));
143 _keyring = new KeyRing(tmpPath());
146 ///////////////////////////////////////////////////////////////////
148 // METHOD NAME : ZYppImpl::~ZYppImpl
149 // METHOD TYPE : Destructor
151 ZYppImpl::~ZYppImpl()
154 //------------------------------------------------------------------------
155 // add/remove resolvables
157 void ZYppImpl::addResolvables (const ResStore& store, bool installed)
159 _pool.insert(store.begin(), store.end(), installed);
162 void ZYppImpl::removeResolvables (const ResStore& store)
164 for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
170 void ZYppImpl::removeInstalledResolvables ()
172 for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
174 ResPool::const_iterator next = it; ++next;
175 if (it->status().isInstalled())
181 DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
185 setPartitions( DiskUsageCounter::detectMountPoints() );
187 return _disk_usage->disk_usage(pool());
190 void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
192 _disk_usage.reset(new DiskUsageCounter());
193 _disk_usage->setMountPoints(mp);
196 DiskUsageCounter::MountPointSet ZYppImpl::getPartitions() const
199 return _disk_usage->getMountPoints();
201 return DiskUsageCounter::detectMountPoints();
204 //------------------------------------------------------------------------
207 Target_Ptr ZYppImpl::target() const
210 ZYPP_THROW(Exception("Target not initialized."));
214 void ZYppImpl::initializeTarget(const Pathname & root)
216 MIL << "initTarget( " << root << endl;
218 if (_target->root() == root) {
219 MIL << "Repeated call to initializeTarget()" << endl;
222 removeInstalledResolvables( );
224 _target = new Target( root );
225 _target->enableStorage( root );
228 void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
230 MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
232 if (_target->root() == root) {
233 MIL << "Repeated call to initTarget()" << endl;
236 removeInstalledResolvables( );
238 _target = new Target( root );
239 _target->enableStorage( root );
242 addResolvables( _target->resolvables(), true );
247 void ZYppImpl::finishTarget()
250 removeInstalledResolvables();
254 //------------------------------------------------------------------------
257 /** \todo Remove workflow from target, lot's of it could be done here,
258 * and target used for transact. */
259 ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
261 if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
263 ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
266 MIL << "Attempt to commit (" << policy_r << ")" << endl;
268 ZYPP_THROW( Exception("Target not initialized.") );
270 ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
272 if (! policy_r.dryRun() ) {
273 // Tag target data invalid, so they are reloaded on the next call to
274 // target->resolvables(). Actually the target should do this without
277 removeInstalledResolvables();
278 if ( policy_r.syncPoolAfterCommit() )
280 // reload new status from target
281 addResolvables( _target->resolvables(), true );
285 MIL << "Commit (" << policy_r << ") returned: "
290 void ZYppImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
293 ZYPP_THROW( Exception("Target not initialized.") );
294 _target->_pimpl->installSrcPackage( srcPackage_r );
297 //------------------------------------------------------------------------
301 void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
303 ResPool mpool( pool() );
304 // assert all requested are available
305 for ( LocaleSet::const_iterator it = locales_r.begin();
306 it != locales_r.end(); ++it )
308 NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
309 if ( select.installedEmpty() && select.availableEmpty() )
310 _pool.insert( Language::availableInstance( *it ) );
314 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
315 it != mpool.byKindEnd<Language>(); ++it )
317 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
318 if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
320 // Language is requested
321 if ( select.installedEmpty() )
323 if ( select.availableEmpty() )
325 // no item ==> provide available to install
326 _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
327 select = nameKindProxy<Language>( mpool, (*it)->name() );
329 // available only ==> to install
330 select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
334 // installed ==> keep it
335 select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
336 if ( ! select.availableEmpty() )
338 // both items ==> keep
339 select.availableBegin()->status().resetTransact( ResStatus::USER );
345 // Language is NOT requested
346 if ( ! select.installedEmpty() )
347 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
348 if ( ! select.availableEmpty() )
349 select.availableBegin()->status().resetTransact( ResStatus::USER );
355 ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
358 ResPool mpool( pool() );
359 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
360 it != mpool.byKindEnd<Language>(); ++it )
362 if ( (*it).status().isUninstalled() ) // available!
363 ret.insert( Locale( (*it)->name() ) );
369 ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
372 ResPool mpool( pool() );
373 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
374 it != mpool.byKindEnd<Language>(); ++it )
376 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
377 if ( ! select.installedEmpty()
378 && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
379 ret.insert( Locale( (*it)->name() ) );
380 else if ( ! select.availableEmpty()
381 && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
382 ret.insert( Locale( (*it)->name() ) );
387 void ZYppImpl::availableLocale( const Locale & locale_r )
389 _pool.insert( Language::availableInstance( locale_r ) );
392 //------------------------------------------------------------------------
395 void ZYppImpl::setArchitecture( const Arch & arch )
397 _architecture = arch;
398 if (_resolver) _resolver->setArchitecture( arch );
401 //------------------------------------------------------------------------
404 Pathname ZYppImpl::homePath() const
405 { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
407 void ZYppImpl::setHomePath( const Pathname & path )
408 { _home_path = path; }
410 Pathname ZYppImpl::tmpPath() const
412 static TmpDir zypp_tmp_dir( TmpPath::defaultLocation(), "zypp." );
413 return zypp_tmp_dir.path();
416 int ZYppImpl::applyLocks()
418 Pathname locksrcPath( "/etc/zypp/locks" );
421 Target_Ptr trg( target() );
423 locksrcPath = trg->root() / locksrcPath;
427 // noop: Someone decided to let target() throw if the ptr is NULL ;(
431 PathInfo locksrc( locksrcPath );
432 if ( locksrc.isFile() )
434 MIL << "Reading locks from '" << locksrcPath << "'" << endl;
435 num = zypp::locks::readLocks( pool(), locksrcPath );
436 MIL << num << " items locked." << endl;
440 MIL << "No file '" << locksrcPath << "' to read locks from" << endl;
444 /******************************************************************
446 ** FUNCTION NAME : operator<<
447 ** FUNCTION TYPE : std::ostream &
449 std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
451 return str << "ZYppImpl";
454 /////////////////////////////////////////////////////////////////
455 } // namespace zypp_detail
456 ///////////////////////////////////////////////////////////////////
457 /////////////////////////////////////////////////////////////////
459 ///////////////////////////////////////////////////////////////////