ZYppImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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       // detect the true architecture
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           // some CPUs report i686 but dont implement cx8 and cmov
00081           // check for both flags in /proc/cpuinfo and downgrade
00082           // to i586 if either is missing (cf bug #18885)
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                         } // flags found
00112                     } // read proc/cpuinfo
00113                 } // proc/cpuinfo opened
00114             } // i686 extra flags check
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     //  METHOD NAME : ZYppImpl::ZYppImpl
00128     //  METHOD TYPE : Constructor
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       //_keyring = new KeyRing(homePath() + Pathname("/keyring/all"), homePath() + Pathname("/keyring/trusted"));
00143       _keyring = new KeyRing(tmpPath());
00144     }
00145 
00147     //
00148     //  METHOD NAME : ZYppImpl::~ZYppImpl
00149     //  METHOD TYPE : Destructor
00150     //
00151     ZYppImpl::~ZYppImpl()
00152     {}
00153 
00154     //------------------------------------------------------------------------
00155     // add/remove resolvables
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     // target
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     // commit
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         // Tag target data invalid, so they are reloaded on the next call to
00274         // target->resolvables(). Actually the target should do this without
00275         // foreign help.
00276         _target->reset();
00277         removeInstalledResolvables();
00278         if ( policy_r.syncPoolAfterCommit() )
00279           {
00280             // reload new status from target
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     // locales
00299 
00301     void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
00302     {
00303       ResPool mpool( pool() );
00304       // assert all requested are available
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       // now adjust status
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               // Language is requested
00321               if ( select.installedEmpty() )
00322                 {
00323                   if ( select.availableEmpty() )
00324                     {
00325                       // no item ==> provide available to install
00326                       _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
00327                       select = nameKindProxy<Language>( mpool, (*it)->name() );
00328                     }
00329                   // available only ==> to install
00330                   select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
00331                 }
00332               else
00333                 {
00334                   // installed ==> keep it
00335                   select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
00336                   if ( ! select.availableEmpty() )
00337                     {
00338                       // both items ==> keep
00339                       select.availableBegin()->status().resetTransact( ResStatus::USER );
00340                     }
00341                 }
00342             }
00343           else
00344             {
00345               // Language is NOT requested
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() ) // available!
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     // architecture
00394 
00395     void ZYppImpl::setArchitecture( const Arch & arch )
00396     {
00397         _architecture = arch;
00398         if (_resolver) _resolver->setArchitecture( arch );
00399     }
00400 
00401     //------------------------------------------------------------------------
00402     // target store path
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         // noop: Someone decided to let target() throw if the ptr is NULL ;(
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      ** FUNCTION NAME : operator<<
00447      ** FUNCTION TYPE : std::ostream &
00448     */
00449     std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
00450     {
00451       return str << "ZYppImpl";
00452     }
00453 
00455   } // namespace zypp_detail
00458 } // namespace zypp

Generated on Tue Sep 25 19:23:11 2007 for libzypp by  doxygen 1.5.3