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