00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <sys/utsname.h>
00014 #include <unistd.h>
00015 #include <iostream>
00016 #include <fstream>
00017 #include "zypp/TmpPath.h"
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/base/String.h"
00020
00021 #include "zypp/zypp_detail/ZYppImpl.h"
00022 #include "zypp/detail/ResImplTraits.h"
00023 #include "zypp/solver/detail/Helper.h"
00024 #include "zypp/target/TargetImpl.h"
00025 #include "zypp/ZYpp.h"
00026 #include "zypp/NVRAD.h"
00027 #include "zypp/Language.h"
00028 #include "zypp/DiskUsageCounter.h"
00029 #include "zypp/NameKindProxy.h"
00030 #include "zypp/Locks.h"
00031
00032 using std::endl;
00033
00035 namespace zypp
00036 {
00037
00038 namespace zypp_detail
00039 {
00040
00041 inline Locale defaultTextLocale()
00042 {
00043 Locale ret( "en" );
00044 const char * envlist[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
00045 for ( const char ** envvar = envlist; *envvar; ++envvar )
00046 {
00047 const char * envlang = getenv( *envvar );
00048 if ( envlang )
00049 {
00050 std::string envstr( envlang );
00051 if ( envstr != "POSIX" && envstr != "C" )
00052 {
00053 Locale lang( envlang );
00054 if ( lang != Locale::noCode )
00055 {
00056 ret = lang;
00057 break;
00058 }
00059 }
00060 }
00061 }
00062 return ret;
00063 }
00064
00065 Arch defaultArchitecture()
00066 {
00067 Arch architecture;
00068
00069
00070 struct utsname buf;
00071 if ( uname( &buf ) < 0 )
00072 {
00073 ERR << "Can't determine system architecture" << endl;
00074 }
00075 else
00076 {
00077 architecture = Arch( buf.machine );
00078 DBG << "uname architecture is '" << buf.machine << "'" << endl;
00079
00080
00081
00082
00083
00084 if ( architecture == Arch_i686 )
00085 {
00086 std::ifstream cpuinfo( "/proc/cpuinfo" );
00087 if ( !cpuinfo )
00088 {
00089 ERR << "Cant open /proc/cpuinfo" << endl;
00090 }
00091 else
00092 {
00093 char infoline[1024];
00094 while ( cpuinfo.good() )
00095 {
00096 if ( !cpuinfo.getline( infoline, 1024, '\n' ) )
00097 {
00098 if ( cpuinfo.eof() )
00099 break;
00100 }
00101 if ( strncmp( infoline, "flags", 5 ) == 0 )
00102 {
00103 std::string flagsline( infoline );
00104 if ( flagsline.find( "cx8" ) == std::string::npos
00105 || flagsline.find( "cmov" ) == std::string::npos )
00106 {
00107 architecture = Arch_i586;
00108 DBG << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl;
00109 }
00110 break;
00111 }
00112 }
00113 }
00114 }
00115 }
00116
00117 if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) )
00118 {
00119 architecture = Arch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) );
00120 WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Setting fake system architecture for test purpuses to: '" << architecture << "'" << endl;
00121 }
00122
00123 return architecture;
00124 }
00126
00127
00128
00129
00130 ZYppImpl::ZYppImpl()
00131 : _textLocale( defaultTextLocale() )
00132 , _pool()
00133 , _target(0)
00134 , _resolver( new Resolver(_pool.accessor()) )
00135 , _architecture( defaultArchitecture() )
00136 {
00137 MIL << "libzypp: " << VERSION << " built " << __DATE__ << " " << __TIME__ << endl;
00138 MIL << "defaultTextLocale: '" << _textLocale << "'" << endl;
00139 MIL << "System architecture is '" << _architecture << "'" << endl;
00140
00141 MIL << "initializing keyring..." << std::endl;
00142
00143 _keyring = new KeyRing(tmpPath());
00144 }
00145
00147
00148
00149
00150
00151 ZYppImpl::~ZYppImpl()
00152 {}
00153
00154
00155
00156
00157 void ZYppImpl::addResolvables (const ResStore& store, bool installed)
00158 {
00159 _pool.insert(store.begin(), store.end(), installed);
00160 }
00161
00162 void ZYppImpl::removeResolvables (const ResStore& store)
00163 {
00164 for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
00165 {
00166 _pool.erase(*it);
00167 }
00168 }
00169
00170 void ZYppImpl::removeInstalledResolvables ()
00171 {
00172 for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
00173 {
00174 ResPool::const_iterator next = it; ++next;
00175 if (it->status().isInstalled())
00176 _pool.erase( *it );
00177 it = next;
00178 }
00179 }
00180
00181 DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
00182 {
00183 if ( ! _disk_usage )
00184 {
00185 setPartitions( DiskUsageCounter::detectMountPoints() );
00186 }
00187 return _disk_usage->disk_usage(pool());
00188 }
00189
00190 void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
00191 {
00192 _disk_usage.reset(new DiskUsageCounter());
00193 _disk_usage->setMountPoints(mp);
00194 }
00195
00196 DiskUsageCounter::MountPointSet ZYppImpl::getPartitions() const
00197 {
00198 if (_disk_usage)
00199 return _disk_usage->getMountPoints();
00200 else
00201 return DiskUsageCounter::detectMountPoints();
00202 }
00203
00204
00205
00206
00207 Target_Ptr ZYppImpl::target() const
00208 {
00209 if (! _target)
00210 ZYPP_THROW(Exception("Target not initialized."));
00211 return _target;
00212 }
00213
00214 void ZYppImpl::initializeTarget(const Pathname & root)
00215 {
00216 MIL << "initTarget( " << root << endl;
00217 if (_target) {
00218 if (_target->root() == root) {
00219 MIL << "Repeated call to initializeTarget()" << endl;
00220 return;
00221 }
00222 removeInstalledResolvables( );
00223 }
00224 _target = new Target( root );
00225 _target->enableStorage( root );
00226 }
00227
00228 void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
00229 {
00230 MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
00231 if (_target) {
00232 if (_target->root() == root) {
00233 MIL << "Repeated call to initTarget()" << endl;
00234 return;
00235 }
00236 removeInstalledResolvables( );
00237 }
00238 _target = new Target( root );
00239 _target->enableStorage( root );
00240 if (!commit_only)
00241 {
00242 addResolvables( _target->resolvables(), true );
00243 }
00244 }
00245
00246
00247 void ZYppImpl::finishTarget()
00248 {
00249 if (_target)
00250 removeInstalledResolvables();
00251 _target = 0;
00252 }
00253
00254
00255
00256
00259 ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
00260 {
00261 if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
00262 {
00263 ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
00264 }
00265
00266 MIL << "Attempt to commit (" << policy_r << ")" << endl;
00267 if (! _target)
00268 ZYPP_THROW( Exception("Target not initialized.") );
00269
00270 ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
00271
00272 if (! policy_r.dryRun() ) {
00273
00274
00275
00276 _target->reset();
00277 removeInstalledResolvables();
00278 if ( policy_r.syncPoolAfterCommit() )
00279 {
00280
00281 addResolvables( _target->resolvables(), true );
00282 }
00283 }
00284
00285 MIL << "Commit (" << policy_r << ") returned: "
00286 << res << endl;
00287 return res;
00288 }
00289
00290 void ZYppImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
00291 {
00292 if (! _target)
00293 ZYPP_THROW( Exception("Target not initialized.") );
00294 _target->_pimpl->installSrcPackage( srcPackage_r );
00295 }
00296
00297
00298
00299
00301 void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
00302 {
00303 ResPool mpool( pool() );
00304
00305 for ( LocaleSet::const_iterator it = locales_r.begin();
00306 it != locales_r.end(); ++it )
00307 {
00308 NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
00309 if ( select.installedEmpty() && select.availableEmpty() )
00310 _pool.insert( Language::availableInstance( *it ) );
00311 }
00312
00313
00314 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00315 it != mpool.byKindEnd<Language>(); ++it )
00316 {
00317 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
00318 if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
00319 {
00320
00321 if ( select.installedEmpty() )
00322 {
00323 if ( select.availableEmpty() )
00324 {
00325
00326 _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
00327 select = nameKindProxy<Language>( mpool, (*it)->name() );
00328 }
00329
00330 select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
00331 }
00332 else
00333 {
00334
00335 select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
00336 if ( ! select.availableEmpty() )
00337 {
00338
00339 select.availableBegin()->status().resetTransact( ResStatus::USER );
00340 }
00341 }
00342 }
00343 else
00344 {
00345
00346 if ( ! select.installedEmpty() )
00347 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
00348 if ( ! select.availableEmpty() )
00349 select.availableBegin()->status().resetTransact( ResStatus::USER );
00350 }
00351 }
00352 }
00353
00355 ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
00356 {
00357 ZYpp::LocaleSet ret;
00358 ResPool mpool( pool() );
00359 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00360 it != mpool.byKindEnd<Language>(); ++it )
00361 {
00362 if ( (*it).status().isUninstalled() )
00363 ret.insert( Locale( (*it)->name() ) );
00364 }
00365 return ret;
00366 }
00367
00369 ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
00370 {
00371 ZYpp::LocaleSet ret;
00372 ResPool mpool( pool() );
00373 for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
00374 it != mpool.byKindEnd<Language>(); ++it )
00375 {
00376 NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
00377 if ( ! select.installedEmpty()
00378 && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
00379 ret.insert( Locale( (*it)->name() ) );
00380 else if ( ! select.availableEmpty()
00381 && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
00382 ret.insert( Locale( (*it)->name() ) );
00383 }
00384 return ret;
00385 }
00386
00387 void ZYppImpl::availableLocale( const Locale & locale_r )
00388 {
00389 _pool.insert( Language::availableInstance( locale_r ) );
00390 }
00391
00392
00393
00394
00395 void ZYppImpl::setArchitecture( const Arch & arch )
00396 {
00397 _architecture = arch;
00398 if (_resolver) _resolver->setArchitecture( arch );
00399 }
00400
00401
00402
00403
00404 Pathname ZYppImpl::homePath() const
00405 { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
00406
00407 void ZYppImpl::setHomePath( const Pathname & path )
00408 { _home_path = path; }
00409
00410 Pathname ZYppImpl::tmpPath() const
00411 {
00412 static TmpDir zypp_tmp_dir( TmpPath::defaultLocation(), "zypp." );
00413 return zypp_tmp_dir.path();
00414 }
00415
00416 int ZYppImpl::applyLocks()
00417 {
00418 Pathname locksrcPath( "/etc/zypp/locks" );
00419 try
00420 {
00421 Target_Ptr trg( target() );
00422 if ( trg )
00423 locksrcPath = trg->root() / locksrcPath;
00424 }
00425 catch ( ... )
00426 {
00427
00428 }
00429
00430 int num=0;
00431 PathInfo locksrc( locksrcPath );
00432 if ( locksrc.isFile() )
00433 {
00434 MIL << "Reading locks from '" << locksrcPath << "'" << endl;
00435 num = zypp::locks::readLocks( pool(), locksrcPath );
00436 MIL << num << " items locked." << endl;
00437 }
00438 else
00439 {
00440 MIL << "No file '" << locksrcPath << "' to read locks from" << endl;
00441 }
00442 return num;
00443 }
00444
00445
00446
00447
00448
00449 std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
00450 {
00451 return str << "ZYppImpl";
00452 }
00453
00455 }
00458 }