libzypp  10.5.0
librpmDb.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include "librpm.h"
00013 
00014 #include <iostream>
00015 
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/PathInfo.h"
00018 #include "zypp/target/rpm/librpmDb.h"
00019 #include "zypp/target/rpm/RpmHeader.h"
00020 #include "zypp/target/rpm/RpmException.h"
00021 
00022 using namespace std;
00023 
00024 namespace zypp
00025 {
00026 namespace target
00027 {
00028 namespace rpm
00029 {
00031 //
00032 //      CLASS NAME : librpmDb::D
00036 class librpmDb::D
00037 {
00038   D & operator=( const D & ); // NO ASSIGNMENT!
00039   D ( const D & );            // NO COPY!
00040 public:
00041 
00042   const Pathname _root;   // root directory for all operations
00043   const Pathname _dbPath; // directory (below root) that contains the rpmdb
00044   rpmts _ts;              // transaction handle, includes database
00045   shared_ptr<RpmException> _error;  // database error
00046 
00047   friend ostream & operator<<( ostream & str, const D & obj )
00048   {
00049     str << "{" << obj._error  << "(" << obj._root << ")" << obj._dbPath << "}";
00050     return str;
00051   }
00052 
00053   D( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r )
00054       : _root  ( root_r )
00055       , _dbPath( dbPath_r )
00056       , _ts    ( 0 )
00057   {
00058     _error.reset();
00059     // set %_dbpath macro
00060     ::addMacro( NULL, "_dbpath", NULL, _dbPath.asString().c_str(), RMIL_CMDLINE );
00061 
00062     _ts = ::rpmtsCreate();
00063     ::rpmtsSetRootDir( _ts, _root.c_str() );
00064 
00065     // check whether to create a new db
00066     PathInfo master( _root + _dbPath + "Packages" );
00067     if ( ! master.isFile() )
00068     {
00069       // init database
00070       if ( filesystem::assert_dir(_root + _dbPath) != 0 )
00071       {
00072         ERR << "Could not create dbpath " << (_root + _dbPath).asString() << endl;
00073         _error = shared_ptr<RpmInitException>(new RpmInitException(_root, _dbPath));
00074         ZYPP_THROW(*_error);
00075       }
00076       int res = ::rpmtsInitDB( _ts, 0644 );
00077       if ( res )
00078       {
00079         ERR << "rpmdbInit error(" << res << "): " << *this << endl;
00080         _error = shared_ptr<RpmInitException>(new RpmInitException(_root, _dbPath));
00081         rpmtsFree(_ts);
00082         ZYPP_THROW(*_error);
00083       }
00084     }
00085 
00086     // open database
00087     int res = ::rpmtsOpenDB( _ts, (readonly_r ? O_RDONLY : O_RDWR ));
00088     if ( res )
00089     {
00090       ERR << "rpmdbOpen error(" << res << "): " << *this << endl;
00091       _error = shared_ptr<RpmDbOpenException>(new RpmDbOpenException(_root, _dbPath));
00092       rpmtsFree(_ts);
00093       ZYPP_THROW(*_error);
00094       return;
00095     }
00096 
00097     DBG << "DBACCESS " << *this << endl;
00098   }
00099 
00100   ~D()
00101   {
00102     if ( _ts )
00103     {
00104       ::rpmtsFree(_ts);
00105     }
00106   }
00107 };
00108 
00110 
00112 //
00113 //      CLASS NAME : librpmDb (ststic interface)
00114 //
00116 
00117 Pathname         librpmDb::_defaultRoot  ( "/" );
00118 Pathname         librpmDb::_defaultDbPath( "/var/lib/rpm" );
00119 librpmDb::constPtr librpmDb::_defaultDb;
00120 bool             librpmDb::_dbBlocked    ( true );
00121 
00123 //
00124 //
00125 //      METHOD NAME : librpmDb::globalInit
00126 //      METHOD TYPE : bool
00127 //
00128 bool librpmDb::globalInit()
00129 {
00130   static bool initialized = false;
00131 
00132   if ( initialized )
00133     return true;
00134 
00135   int rc = ::rpmReadConfigFiles( NULL, NULL );
00136   if ( rc )
00137   {
00138     ERR << "rpmReadConfigFiles returned " << rc << endl;
00139     return false;
00140   }
00141 
00142   initialized = true; // Necessary to be able to use exand().
00143 
00144 #define OUTVAL(n) << " (" #n ":" << expand( "%{" #n "}" ) << ")"
00145   MIL << "librpm init done:"
00146   OUTVAL(_target)
00147   OUTVAL(_dbpath)
00148   << endl;
00149 #undef OUTVAL
00150   return initialized;
00151 }
00152 
00154 //
00155 //
00156 //      METHOD NAME : librpmDb::expand
00157 //      METHOD TYPE : std::string
00158 //
00159 std::string librpmDb::expand( const std::string & macro_r )
00160 {
00161   if ( ! globalInit() )
00162     return macro_r;  // unexpanded
00163 
00164   char * val = ::rpmExpand( macro_r.c_str(), NULL );
00165   if ( !val )
00166     return "";
00167 
00168   string ret( val );
00169   free( val );
00170   return ret;
00171 }
00172 
00174 //
00175 //
00176 //      METHOD NAME : librpmDb::newLibrpmDb
00177 //      METHOD TYPE : librpmDb *
00178 //
00179 librpmDb * librpmDb::newLibrpmDb( Pathname root_r, Pathname dbPath_r, bool readonly_r )
00180 {
00181   // check arguments
00182   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
00183   {
00184     ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
00185   }
00186 
00187   // initialize librpm
00188   if ( ! globalInit() )
00189   {
00190     ZYPP_THROW(GlobalRpmInitException());
00191   }
00192 
00193   // open rpmdb
00194   librpmDb * ret = 0;
00195   try
00196   {
00197     ret = new librpmDb( root_r, dbPath_r, readonly_r );
00198   }
00199   catch (const RpmException & excpt_r)
00200   {
00201     ZYPP_CAUGHT(excpt_r);
00202     delete ret;
00203     ret = 0;
00204     ZYPP_RETHROW(excpt_r);
00205   }
00206   return ret;
00207 }
00208 
00210 //
00211 //
00212 //      METHOD NAME : librpmDb::dbAccess
00213 //      METHOD TYPE : PMError
00214 //
00215 void librpmDb::dbAccess( const Pathname & root_r, const Pathname & dbPath_r )
00216 {
00217   // check arguments
00218   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
00219   {
00220     ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
00221   }
00222 
00223   if ( _defaultDb )
00224   {
00225     // already accessing a database: switching is not allowed.
00226     if ( _defaultRoot == root_r && _defaultDbPath == dbPath_r )
00227       return;
00228     else
00229     {
00230       ZYPP_THROW(RpmDbAlreadyOpenException(_defaultRoot, _defaultDbPath, root_r, dbPath_r));
00231     }
00232   }
00233 
00234   // got no database: we could switch to a new one (even if blocked!)
00235   _defaultRoot = root_r;
00236   _defaultDbPath = dbPath_r;
00237   MIL << "Set new database location: " << stringPath( _defaultRoot, _defaultDbPath ) << endl;
00238 
00239   return dbAccess();
00240 }
00241 
00243 //
00244 //
00245 //      METHOD NAME : librpmDb::dbAccess
00246 //      METHOD TYPE : PMError
00247 //
00248 void librpmDb::dbAccess()
00249 {
00250   if ( _dbBlocked )
00251   {
00252     ZYPP_THROW(RpmAccessBlockedException(_defaultRoot, _defaultDbPath));
00253   }
00254 
00255   if ( !_defaultDb )
00256   {
00257     // get access
00258     _defaultDb = newLibrpmDb( _defaultRoot, _defaultDbPath, /*readonly*/true );
00259   }
00260 }
00261 
00263 //
00264 //
00265 //      METHOD NAME : librpmDb::dbAccess
00266 //      METHOD TYPE : PMError
00267 //
00268 void librpmDb::dbAccess( librpmDb::constPtr & ptr_r )
00269 {
00270   try
00271   {
00272     dbAccess();
00273   }
00274   catch (const RpmException & excpt_r)
00275   {
00276     ZYPP_CAUGHT(excpt_r);
00277     ptr_r = 0;
00278     ZYPP_RETHROW(excpt_r);
00279   }
00280   ptr_r = _defaultDb;
00281 }
00282 
00284 //
00285 //
00286 //      METHOD NAME : librpmDb::dbRelease
00287 //      METHOD TYPE : unsigned
00288 //
00289 unsigned librpmDb::dbRelease( bool force_r )
00290 {
00291   if ( !_defaultDb )
00292   {
00293     return 0;
00294   }
00295 
00296   unsigned outstanding = _defaultDb->refCount() - 1; // refCount can't be 0
00297 
00298   switch ( outstanding )
00299   {
00300   default:
00301     if ( !force_r )
00302     {
00303       DBG << "dbRelease: keep access, outstanding " << outstanding << endl;
00304       break;
00305     }
00306     // else fall through:
00307   case 0:
00308     DBG << "dbRelease: release" << (force_r && outstanding ? "(forced)" : "")
00309     << ", outstanding " << outstanding << endl;
00310 
00311     _defaultDb->_d._error = shared_ptr<RpmAccessBlockedException>(new RpmAccessBlockedException(_defaultDb->_d._root, _defaultDb->_d._dbPath));
00312     // tag handle invalid
00313     _defaultDb = 0;
00314     break;
00315   }
00316 
00317   return outstanding;
00318 }
00319 
00321 //
00322 //
00323 //      METHOD NAME : librpmDb::blockAccess
00324 //      METHOD TYPE : unsigned
00325 //
00326 unsigned librpmDb::blockAccess()
00327 {
00328   MIL << "Block access" << endl;
00329   _dbBlocked = true;
00330   return dbRelease( /*force*/true );
00331 }
00332 
00334 //
00335 //
00336 //      METHOD NAME : librpmDb::unblockAccess
00337 //      METHOD TYPE : void
00338 //
00339 void librpmDb::unblockAccess()
00340 {
00341   MIL << "Unblock access" << endl;
00342   _dbBlocked = false;
00343 }
00344 
00346 //
00347 //
00348 //      METHOD NAME : librpmDb::dumpState
00349 //      METHOD TYPE : ostream &
00350 //
00351 ostream & librpmDb::dumpState( ostream & str )
00352 {
00353   if ( !_defaultDb )
00354   {
00355     return str << "[librpmDb " << (_dbBlocked?"BLOCKED":"CLOSED") << " " << stringPath( _defaultRoot, _defaultDbPath ) << "]";
00356   }
00357   return str << "[" << _defaultDb << "]";
00358 }
00359 
00361 //
00362 //      CLASS NAME : librpmDb (internal database handle interface (nonstatic))
00363 //
00365 
00367 //
00368 //
00369 //      METHOD NAME : librpmDb::librpmDb
00370 //      METHOD TYPE : Constructor
00371 //
00372 //      DESCRIPTION :
00373 //
00374 librpmDb::librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r )
00375     : _d( * new D( root_r, dbPath_r, readonly_r ) )
00376 {}
00377 
00379 //
00380 //
00381 //      METHOD NAME : librpmDb::~librpmDb
00382 //      METHOD TYPE : Destructor
00383 //
00384 //      DESCRIPTION :
00385 //
00386 librpmDb::~librpmDb()
00387 {
00388   delete &_d;
00389 }
00390 
00392 //
00393 //
00394 //      METHOD NAME : librpmDb::unref_to
00395 //      METHOD TYPE : void
00396 //
00397 void librpmDb::unref_to( unsigned refCount_r ) const
00398 {
00399   if ( refCount_r == 1 )
00400   {
00401     dbRelease();
00402   }
00403 }
00404 
00406 //
00407 //
00408 //      METHOD NAME : librpmDb::root
00409 //      METHOD TYPE : const Pathname &
00410 //
00411 const Pathname & librpmDb::root() const
00412 {
00413   return _d._root;
00414 }
00415 
00417 //
00418 //
00419 //      METHOD NAME : librpmDb::dbPath
00420 //      METHOD TYPE : const Pathname &
00421 //
00422 const Pathname & librpmDb::dbPath() const
00423 {
00424   return _d._dbPath;
00425 }
00426 
00428 //
00429 //
00430 //      METHOD NAME : librpmDb::error
00431 //      METHOD TYPE : PMError
00432 //
00433 shared_ptr<RpmException> librpmDb::error() const
00434 {
00435   return _d._error;
00436 }
00437 
00439 //
00440 //
00441 //      METHOD NAME : librpmDb::empty
00442 //      METHOD TYPE : bool
00443 //
00444 bool librpmDb::empty() const
00445 {
00446   return( valid() && ! *db_const_iterator( this ) );
00447 }
00448 
00450 //
00451 //
00452 //      METHOD NAME : librpmDb::size
00453 //      METHOD TYPE : unsigned
00454 //
00455 unsigned librpmDb::size() const
00456 {
00457   unsigned count = 0;
00458   if ( valid() )
00459   {
00460     db_const_iterator it( this );
00461     for ( db_const_iterator it( this ); *it; ++it )
00462       ++count;
00463   }
00464   return count;
00465 }
00466 
00468 //
00469 //
00470 //      METHOD NAME : librpmDb::dont_call_it
00471 //      METHOD TYPE : void *
00472 //
00473 void * librpmDb::dont_call_it() const
00474 {
00475   return rpmtsGetRdb(_d._ts);
00476 }
00477 
00479 //
00480 //
00481 //      METHOD NAME : librpmDb::dumpOn
00482 //      METHOD TYPE : ostream &
00483 //
00484 //      DESCRIPTION :
00485 //
00486 ostream & librpmDb::dumpOn( ostream & str ) const
00487 {
00488   ReferenceCounted::dumpOn( str ) << _d;
00489   return str;
00490 }
00491 
00493 //
00494 //      CLASS NAME : librpmDb::DbDirInfo
00495 //
00497 
00499 //
00500 //
00501 //      METHOD NAME : librpmDb::DbDirInfo::DbDirInfo
00502 //      METHOD TYPE : Constructor
00503 //
00504 librpmDb::DbDirInfo::DbDirInfo( const Pathname & root_r, const Pathname & dbPath_r )
00505     : _root( root_r )
00506     , _dbPath( dbPath_r )
00507 {
00508   // check and adjust arguments
00509   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
00510   {
00511     ERR << "Relative path for root(" << _root << ") or dbPath(" << _dbPath << ")" << endl;
00512   }
00513   else
00514   {
00515     _dbDir   ( _root + _dbPath );
00516     _dbV4    ( _dbDir.path() + "Packages" );
00517     _dbV3    ( _dbDir.path() + "packages.rpm" );
00518     _dbV3ToV4( _dbDir.path() + "packages.rpm3" );
00519     DBG << *this << endl;
00520   }
00521 }
00522 
00524 //
00525 //
00526 //      METHOD NAME : librpmDb::DbDirInfo::update
00527 //      METHOD TYPE : void
00528 //
00529 void librpmDb::DbDirInfo::restat()
00530 {
00531   _dbDir();
00532   _dbV4();
00533   _dbV3();
00534   _dbV3ToV4();
00535   DBG << *this << endl;
00536 }
00537 
00538 /******************************************************************
00539 **
00540 **
00541 **      FUNCTION NAME : operator<<
00542 **      FUNCTION TYPE : std::ostream &
00543 */
00544 std::ostream & operator<<( std::ostream & str, const librpmDb::DbDirInfo & obj )
00545 {
00546   if ( obj.illegalArgs() )
00547   {
00548     str << "ILLEGAL: '(" << obj.root() << ")" << obj.dbPath() << "'";
00549   }
00550   else
00551   {
00552     str << "'(" << obj.root() << ")" << obj.dbPath() << "':" << endl;
00553     str << "  Dir:    " << obj._dbDir << endl;
00554     str << "  V4:     " << obj._dbV4 << endl;
00555     str << "  V3:     " << obj._dbV3 << endl;
00556     str << "  V3ToV4: " << obj._dbV3ToV4;
00557   }
00558   return str;
00559 }
00560 
00562 //
00563 //      CLASS NAME : librpmDb::db_const_iterator::D
00567 class librpmDb::db_const_iterator::D
00568 {
00569   D & operator=( const D & ); // NO ASSIGNMENT!
00570   D ( const D & );            // NO COPY!
00571 public:
00572 
00573   librpmDb::constPtr     _dbptr;
00574   shared_ptr<RpmException> _dberr;
00575 
00576   RpmHeader::constPtr _hptr;
00577   rpmdbMatchIterator   _mi;
00578 
00579   D( librpmDb::constPtr dbptr_r )
00580       : _dbptr( dbptr_r )
00581       , _mi( 0 )
00582   {
00583     if ( !_dbptr )
00584     {
00585       try
00586       {
00587         librpmDb::dbAccess( _dbptr );
00588       }
00589       catch (const RpmException & excpt_r)
00590       {
00591         ZYPP_CAUGHT(excpt_r);
00592       }
00593       if ( !_dbptr )
00594       {
00595         WAR << "No database access: " << _dberr << endl;
00596       }
00597     }
00598     else
00599     {
00600       destroy(); // Checks whether _dbptr still valid
00601     }
00602   }
00603 
00604   ~D()
00605   {
00606     if ( _mi )
00607     {
00608       ::rpmdbFreeIterator( _mi );
00609     }
00610   }
00611 
00616   bool create( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
00617   {
00618     destroy();
00619     if ( ! _dbptr )
00620       return false;
00621     _mi = ::rpmtsInitIterator( _dbptr->_d._ts, rpmTag(rpmtag), keyp, keylen );
00622     return _mi;
00623   }
00624 
00629   bool destroy()
00630   {
00631     if ( _mi )
00632     {
00633       _mi = ::rpmdbFreeIterator( _mi );
00634       _hptr = 0;
00635     }
00636     if ( _dbptr && _dbptr->error() )
00637     {
00638       _dberr = _dbptr->error();
00639       WAR << "Lost database access: " << _dberr << endl;
00640       _dbptr = 0;
00641     }
00642     return false;
00643   }
00644 
00649   bool advance()
00650   {
00651     if ( !_mi )
00652       return false;
00653     Header h = ::rpmdbNextIterator( _mi );
00654     if ( ! h )
00655     {
00656       destroy();
00657       return false;
00658     }
00659     _hptr = new RpmHeader( h );
00660     return true;
00661   }
00662 
00666   bool init( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
00667   {
00668     if ( ! create( rpmtag, keyp, keylen ) )
00669       return false;
00670     return advance();
00671   }
00672 
00677   bool set( int off_r )
00678   {
00679     if ( ! create( RPMDBI_PACKAGES ) )
00680       return false;
00681 #warning TESTCASE: rpmdbAppendIterator and (non)sequential access?
00682     ::rpmdbAppendIterator( _mi, &off_r, 1 );
00683     return advance();
00684   }
00685 
00686   unsigned offset()
00687   {
00688     return( _mi ? ::rpmdbGetIteratorOffset( _mi ) : 0 );
00689   }
00690 
00691   int size()
00692   {
00693     if ( !_mi )
00694       return 0;
00695     int ret = ::rpmdbGetIteratorCount( _mi );
00696 #warning TESTCASE: rpmdbGetIteratorCount returns 0 on sequential access?
00697     return( ret ? ret : -1 ); // -1: sequential access
00698   }
00699 };
00700 
00702 
00704 //
00705 //      CLASS NAME : librpmDb::Ptr::db_const_iterator
00706 //
00708 
00710 //
00711 //
00712 //      METHOD NAME : librpmDb::db_const_iterator::db_iterator
00713 //      METHOD TYPE : Constructor
00714 //
00715 librpmDb::db_const_iterator::db_const_iterator( librpmDb::constPtr dbptr_r )
00716     : _d( * new D( dbptr_r ) )
00717 {
00718   findAll();
00719 }
00720 
00722 //
00723 //
00724 //      METHOD NAME : librpmDb::db_const_iterator::~db_const_iterator
00725 //      METHOD TYPE : Destructor
00726 //
00727 librpmDb::db_const_iterator::~db_const_iterator()
00728 {
00729   delete &_d;
00730 }
00731 
00733 //
00734 //
00735 //      METHOD NAME : librpmDb::db_const_iterator::operator++
00736 //      METHOD TYPE : void
00737 //
00738 void librpmDb::db_const_iterator::operator++()
00739 {
00740   _d.advance();
00741 }
00742 
00744 //
00745 //
00746 //      METHOD NAME : librpmDb::db_const_iterator::dbHdrNum
00747 //      METHOD TYPE : unsigned
00748 //
00749 unsigned librpmDb::db_const_iterator::dbHdrNum() const
00750 {
00751   return _d.offset();
00752 }
00753 
00755 //
00756 //
00757 //      METHOD NAME : librpmDb::db_const_iterator::operator*
00758 //      METHOD TYPE : const RpmHeader::constPtr &
00759 //
00760 const RpmHeader::constPtr & librpmDb::db_const_iterator::operator*() const
00761 {
00762   return _d._hptr;
00763 }
00764 
00766 //
00767 //
00768 //      METHOD NAME : librpmDb::db_const_iterator::dbError
00769 //      METHOD TYPE : PMError
00770 //
00771 shared_ptr<RpmException> librpmDb::db_const_iterator::dbError() const
00772 {
00773   if ( _d._dbptr )
00774     return _d._dbptr->error();
00775 
00776   return _d._dberr;
00777 }
00778 
00779 /******************************************************************
00780 **
00781 **
00782 **      FUNCTION NAME : operator<<
00783 **      FUNCTION TYPE : ostream &
00784 */
00785 ostream & operator<<( ostream & str, const librpmDb::db_const_iterator & obj )
00786 {
00787   str << "db_const_iterator(" << obj._d._dbptr
00788   << " Size:" << obj._d.size()
00789   << " HdrNum:" << obj._d.offset()
00790   << ")";
00791   return str;
00792 }
00793 
00795 //
00796 //
00797 //      METHOD NAME : librpmDb::db_const_iterator::findAll
00798 //      METHOD TYPE : bool
00799 //
00800 bool librpmDb::db_const_iterator::findAll()
00801 {
00802   return _d.init( RPMDBI_PACKAGES );
00803 }
00804 
00806 //
00807 //
00808 //      METHOD NAME : librpmDb::db_const_iterator::findByFile
00809 //      METHOD TYPE : bool
00810 //
00811 bool librpmDb::db_const_iterator::findByFile( const std::string & file_r )
00812 {
00813   return _d.init( RPMTAG_BASENAMES, file_r.c_str() );
00814 }
00815 
00817 //
00818 //
00819 //      METHOD NAME : librpmDb::db_const_iterator::findByProvides
00820 //      METHOD TYPE : bool
00821 //
00822 bool librpmDb::db_const_iterator::findByProvides( const std::string & tag_r )
00823 {
00824   return _d.init( RPMTAG_PROVIDENAME, tag_r.c_str() );
00825 }
00826 
00828 //
00829 //
00830 //      METHOD NAME : librpmDb::db_const_iterator::findByRequiredBy
00831 //      METHOD TYPE : bool
00832 //
00833 bool librpmDb::db_const_iterator::findByRequiredBy( const std::string & tag_r )
00834 {
00835   return _d.init( RPMTAG_REQUIRENAME, tag_r.c_str() );
00836 }
00837 
00839 //
00840 //
00841 //      METHOD NAME : librpmDb::db_const_iterator::findByConflicts
00842 //      METHOD TYPE : bool
00843 //
00844 bool librpmDb::db_const_iterator::findByConflicts( const std::string & tag_r )
00845 {
00846   return _d.init( RPMTAG_CONFLICTNAME, tag_r.c_str() );
00847 }
00848 
00850 //
00851 //
00852 //      METHOD NAME : librpmDb::findByName
00853 //      METHOD TYPE : bool
00854 //
00855 bool librpmDb::db_const_iterator::findByName( const string & name_r )
00856 {
00857   return _d.init( RPMTAG_NAME, name_r.c_str() );
00858 }
00859 
00861 //
00862 //
00863 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
00864 //      METHOD TYPE : bool
00865 //
00866 bool librpmDb::db_const_iterator::findPackage( const string & name_r )
00867 {
00868   if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
00869     return false;
00870 
00871   if ( _d.size() == 1 )
00872     return true;
00873 
00874   // check installtime on multiple entries
00875   int match    = 0;
00876   time_t itime = 0;
00877   for ( ; operator*(); operator++() )
00878   {
00879     if ( operator*()->tag_installtime() > itime )
00880     {
00881       match = _d.offset();
00882       itime = operator*()->tag_installtime();
00883     }
00884   }
00885 
00886   return _d.set( match );
00887 }
00888 
00890 //
00891 //
00892 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
00893 //      METHOD TYPE : bool
00894 //
00895 bool librpmDb::db_const_iterator::findPackage( const std::string & name_r, const Edition & ed_r )
00896 {
00897   if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
00898     return false;
00899 
00900   for ( ; operator*(); operator++() )
00901   {
00902     if ( ed_r == operator*()->tag_edition() )
00903     {
00904       int match = _d.offset();
00905       return _d.set( match );
00906     }
00907   }
00908 
00909   return _d.destroy();
00910 }
00911 
00913 //
00914 //
00915 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
00916 //      METHOD TYPE : bool
00917 //
00918 bool librpmDb::db_const_iterator::findPackage( const Package::constPtr & which_r )
00919 {
00920   if ( ! which_r )
00921     return _d.destroy();
00922 
00923   return findPackage( which_r->name(), which_r->edition() );
00924 }
00925 
00926 } // namespace rpm
00927 } // namespace target
00928 } // namespace zypp