cc419dd63511e062961b72282bce077aa2badce3
[platform/upstream/libzypp.git] / zypp / target / rpm / librpmDb.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/librpmDb.cc
10  *
11 */
12 #include "librpm.h"
13
14 #include <iostream>
15
16 #include "zypp/base/Logger.h"
17 #include "zypp/PathInfo.h"
18 #include "zypp/target/rpm/librpmDb.h"
19 #include "zypp/target/rpm/RpmHeader.h"
20 #include "zypp/target/rpm/RpmException.h"
21
22 using namespace std;
23
24 namespace zypp
25 {
26 namespace target
27 {
28 namespace rpm
29 {
30 ///////////////////////////////////////////////////////////////////
31 //
32 //      CLASS NAME : librpmDb::D
33 /**
34  * @short librpmDb internal database handle
35  **/
36 class librpmDb::D
37 {
38   D & operator=( const D & ); // NO ASSIGNMENT!
39   D ( const D & );            // NO COPY!
40 public:
41
42   const Pathname _root;   // root directory for all operations
43   const Pathname _dbPath; // directory (below root) that contains the rpmdb
44   rpmts _ts;              // transaction handle, includes database
45   shared_ptr<RpmException> _error;  // database error
46
47   friend ostream & operator<<( ostream & str, const D & obj )
48   {
49     str << "{" << obj._error  << "(" << obj._root << ")" << obj._dbPath << "}";
50     return str;
51   }
52
53   D( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r )
54       : _root  ( root_r )
55       , _dbPath( dbPath_r )
56       , _ts    ( 0 )
57   {
58     _error.reset();
59     // set %_dbpath macro
60     ::addMacro( NULL, "_dbpath", NULL, _dbPath.asString().c_str(), RMIL_CMDLINE );
61
62     _ts = ::rpmtsCreate();
63     ::rpmtsSetRootDir( _ts, _root.c_str() );
64
65     // check whether to create a new db
66     PathInfo master( _root + _dbPath + "Packages" );
67     if ( ! master.isFile() )
68     {
69       // init database
70       if ( filesystem::assert_dir(_root + _dbPath) != 0 )
71       {
72         ERR << "Could not create dbpath " << (_root + _dbPath).asString() << endl;
73         _error = shared_ptr<RpmInitException>(new RpmInitException(_root, _dbPath));
74         ZYPP_THROW(*_error);
75       }
76       int res = ::rpmtsInitDB( _ts, 0644 );
77       if ( res )
78       {
79         ERR << "rpmdbInit error(" << res << "): " << *this << endl;
80         _error = shared_ptr<RpmInitException>(new RpmInitException(_root, _dbPath));
81         rpmtsFree(_ts);
82         ZYPP_THROW(*_error);
83       }
84     }
85
86     // open database
87     int res = ::rpmtsOpenDB( _ts, (readonly_r ? O_RDONLY : O_RDWR ));
88     if ( res )
89     {
90       ERR << "rpmdbOpen error(" << res << "): " << *this << endl;
91       _error = shared_ptr<RpmDbOpenException>(new RpmDbOpenException(_root, _dbPath));
92       rpmtsFree(_ts);
93       ZYPP_THROW(*_error);
94       return;
95     }
96
97     DBG << "DBACCESS " << *this << endl;
98   }
99
100   ~D()
101   {
102     if ( _ts )
103     {
104       ::rpmtsFree(_ts);
105     }
106   }
107 };
108
109 ///////////////////////////////////////////////////////////////////
110
111 ///////////////////////////////////////////////////////////////////
112 //
113 //      CLASS NAME : librpmDb (ststic interface)
114 //
115 ///////////////////////////////////////////////////////////////////
116
117 Pathname         librpmDb::_defaultRoot  ( "/" );
118 Pathname         librpmDb::_defaultDbPath( "/var/lib/rpm" );
119 librpmDb::constPtr librpmDb::_defaultDb;
120 bool             librpmDb::_dbBlocked    ( true );
121
122 ///////////////////////////////////////////////////////////////////
123 //
124 //
125 //      METHOD NAME : librpmDb::globalInit
126 //      METHOD TYPE : bool
127 //
128 bool librpmDb::globalInit()
129 {
130   static bool initialized = false;
131
132   if ( initialized )
133     return true;
134
135   int rc = ::rpmReadConfigFiles( NULL, NULL );
136   if ( rc )
137   {
138     ERR << "rpmReadConfigFiles returned " << rc << endl;
139     return false;
140   }
141
142   initialized = true; // Necessary to be able to use exand().
143
144 #define OUTVAL(n) << " (" #n ":" << expand( "%{" #n "}" ) << ")"
145   MIL << "librpm init done:"
146   OUTVAL(_target)
147   OUTVAL(_dbpath)
148   << endl;
149 #undef OUTVAL
150   return initialized;
151 }
152
153 ///////////////////////////////////////////////////////////////////
154 //
155 //
156 //      METHOD NAME : librpmDb::expand
157 //      METHOD TYPE : std::string
158 //
159 std::string librpmDb::expand( const std::string & macro_r )
160 {
161   if ( ! globalInit() )
162     return macro_r;  // unexpanded
163
164   char * val = ::rpmExpand( macro_r.c_str(), NULL );
165   if ( !val )
166     return "";
167
168   string ret( val );
169   free( val );
170   return ret;
171 }
172
173 ///////////////////////////////////////////////////////////////////
174 //
175 //
176 //      METHOD NAME : librpmDb::newLibrpmDb
177 //      METHOD TYPE : librpmDb *
178 //
179 librpmDb * librpmDb::newLibrpmDb( Pathname root_r, Pathname dbPath_r, bool readonly_r )
180 {
181   // check arguments
182   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
183   {
184     ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
185   }
186
187   // initialize librpm
188   if ( ! globalInit() )
189   {
190     ZYPP_THROW(GlobalRpmInitException());
191   }
192
193   // open rpmdb
194   librpmDb * ret = 0;
195   try
196   {
197     ret = new librpmDb( root_r, dbPath_r, readonly_r );
198   }
199   catch (const RpmException & excpt_r)
200   {
201     ZYPP_CAUGHT(excpt_r);
202     delete ret;
203     ret = 0;
204     ZYPP_RETHROW(excpt_r);
205   }
206   return ret;
207 }
208
209 ///////////////////////////////////////////////////////////////////
210 //
211 //
212 //      METHOD NAME : librpmDb::dbAccess
213 //      METHOD TYPE : PMError
214 //
215 void librpmDb::dbAccess( const Pathname & root_r, const Pathname & dbPath_r )
216 {
217   // check arguments
218   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
219   {
220     ZYPP_THROW(RpmInvalidRootException(root_r, dbPath_r));
221   }
222
223   if ( _defaultDb )
224   {
225     // already accessing a database: switching is not allowed.
226     if ( _defaultRoot == root_r && _defaultDbPath == dbPath_r )
227       return;
228     else
229     {
230       ZYPP_THROW(RpmDbAlreadyOpenException(_defaultRoot, _defaultDbPath, root_r, dbPath_r));
231     }
232   }
233
234   // got no database: we could switch to a new one (even if blocked!)
235   _defaultRoot = root_r;
236   _defaultDbPath = dbPath_r;
237   MIL << "Set new database location: " << stringPath( _defaultRoot, _defaultDbPath ) << endl;
238
239   return dbAccess();
240 }
241
242 ///////////////////////////////////////////////////////////////////
243 //
244 //
245 //      METHOD NAME : librpmDb::dbAccess
246 //      METHOD TYPE : PMError
247 //
248 void librpmDb::dbAccess()
249 {
250   if ( _dbBlocked )
251   {
252     ZYPP_THROW(RpmAccessBlockedException(_defaultRoot, _defaultDbPath));
253   }
254
255   if ( !_defaultDb )
256   {
257     // get access
258     _defaultDb = newLibrpmDb( _defaultRoot, _defaultDbPath, /*readonly*/true );
259   }
260 }
261
262 ///////////////////////////////////////////////////////////////////
263 //
264 //
265 //      METHOD NAME : librpmDb::dbAccess
266 //      METHOD TYPE : PMError
267 //
268 void librpmDb::dbAccess( librpmDb::constPtr & ptr_r )
269 {
270   try
271   {
272     dbAccess();
273   }
274   catch (const RpmException & excpt_r)
275   {
276     ZYPP_CAUGHT(excpt_r);
277     ptr_r = 0;
278     ZYPP_RETHROW(excpt_r);
279   }
280   ptr_r = _defaultDb;
281 }
282
283 ///////////////////////////////////////////////////////////////////
284 //
285 //
286 //      METHOD NAME : librpmDb::dbRelease
287 //      METHOD TYPE : unsigned
288 //
289 unsigned librpmDb::dbRelease( bool force_r )
290 {
291   if ( !_defaultDb )
292   {
293     return 0;
294   }
295
296   unsigned outstanding = _defaultDb->refCount() - 1; // refCount can't be 0
297
298   switch ( outstanding )
299   {
300   default:
301     if ( !force_r )
302     {
303       DBG << "dbRelease: keep access, outstanding " << outstanding << endl;
304       break;
305     }
306     // else fall through:
307   case 0:
308     DBG << "dbRelease: release" << (force_r && outstanding ? "(forced)" : "")
309     << ", outstanding " << outstanding << endl;
310
311     _defaultDb->_d._error = shared_ptr<RpmAccessBlockedException>(new RpmAccessBlockedException(_defaultDb->_d._root, _defaultDb->_d._dbPath));
312     // tag handle invalid
313     _defaultDb = 0;
314     break;
315   }
316
317   return outstanding;
318 }
319
320 ///////////////////////////////////////////////////////////////////
321 //
322 //
323 //      METHOD NAME : librpmDb::blockAccess
324 //      METHOD TYPE : unsigned
325 //
326 unsigned librpmDb::blockAccess()
327 {
328   MIL << "Block access" << endl;
329   _dbBlocked = true;
330   return dbRelease( /*force*/true );
331 }
332
333 ///////////////////////////////////////////////////////////////////
334 //
335 //
336 //      METHOD NAME : librpmDb::unblockAccess
337 //      METHOD TYPE : void
338 //
339 void librpmDb::unblockAccess()
340 {
341   MIL << "Unblock access" << endl;
342   _dbBlocked = false;
343 }
344
345 ///////////////////////////////////////////////////////////////////
346 //
347 //
348 //      METHOD NAME : librpmDb::dumpState
349 //      METHOD TYPE : ostream &
350 //
351 ostream & librpmDb::dumpState( ostream & str )
352 {
353   if ( !_defaultDb )
354   {
355     return str << "[librpmDb " << (_dbBlocked?"BLOCKED":"CLOSED") << " " << stringPath( _defaultRoot, _defaultDbPath ) << "]";
356   }
357   return str << "[" << _defaultDb << "]";
358 }
359
360 ///////////////////////////////////////////////////////////////////
361 //
362 //      CLASS NAME : librpmDb (internal database handle interface (nonstatic))
363 //
364 ///////////////////////////////////////////////////////////////////
365
366 ///////////////////////////////////////////////////////////////////
367 //
368 //
369 //      METHOD NAME : librpmDb::librpmDb
370 //      METHOD TYPE : Constructor
371 //
372 //      DESCRIPTION :
373 //
374 librpmDb::librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r )
375     : _d( * new D( root_r, dbPath_r, readonly_r ) )
376 {}
377
378 ///////////////////////////////////////////////////////////////////
379 //
380 //
381 //      METHOD NAME : librpmDb::~librpmDb
382 //      METHOD TYPE : Destructor
383 //
384 //      DESCRIPTION :
385 //
386 librpmDb::~librpmDb()
387 {
388   delete &_d;
389 }
390
391 ///////////////////////////////////////////////////////////////////
392 //
393 //
394 //      METHOD NAME : librpmDb::unref_to
395 //      METHOD TYPE : void
396 //
397 void librpmDb::unref_to( unsigned refCount_r ) const
398 {
399   if ( refCount_r == 1 )
400   {
401     dbRelease();
402   }
403 }
404
405 ///////////////////////////////////////////////////////////////////
406 //
407 //
408 //      METHOD NAME : librpmDb::root
409 //      METHOD TYPE : const Pathname &
410 //
411 const Pathname & librpmDb::root() const
412 {
413   return _d._root;
414 }
415
416 ///////////////////////////////////////////////////////////////////
417 //
418 //
419 //      METHOD NAME : librpmDb::dbPath
420 //      METHOD TYPE : const Pathname &
421 //
422 const Pathname & librpmDb::dbPath() const
423 {
424   return _d._dbPath;
425 }
426
427 ///////////////////////////////////////////////////////////////////
428 //
429 //
430 //      METHOD NAME : librpmDb::error
431 //      METHOD TYPE : PMError
432 //
433 shared_ptr<RpmException> librpmDb::error() const
434 {
435   return _d._error;
436 }
437
438 ///////////////////////////////////////////////////////////////////
439 //
440 //
441 //      METHOD NAME : librpmDb::empty
442 //      METHOD TYPE : bool
443 //
444 bool librpmDb::empty() const
445 {
446   return( valid() && ! *db_const_iterator( this ) );
447 }
448
449 ///////////////////////////////////////////////////////////////////
450 //
451 //
452 //      METHOD NAME : librpmDb::size
453 //      METHOD TYPE : unsigned
454 //
455 unsigned librpmDb::size() const
456 {
457   unsigned count = 0;
458   if ( valid() )
459   {
460     db_const_iterator it( this );
461     for ( db_const_iterator it( this ); *it; ++it )
462       ++count;
463   }
464   return count;
465 }
466
467 ///////////////////////////////////////////////////////////////////
468 //
469 //
470 //      METHOD NAME : librpmDb::dont_call_it
471 //      METHOD TYPE : void *
472 //
473 void * librpmDb::dont_call_it() const
474 {
475   return rpmtsGetRdb(_d._ts);
476 }
477
478 ///////////////////////////////////////////////////////////////////
479 //
480 //
481 //      METHOD NAME : librpmDb::dumpOn
482 //      METHOD TYPE : ostream &
483 //
484 //      DESCRIPTION :
485 //
486 ostream & librpmDb::dumpOn( ostream & str ) const
487 {
488   ReferenceCounted::dumpOn( str ) << _d;
489   return str;
490 }
491
492 ///////////////////////////////////////////////////////////////////
493 //
494 //      CLASS NAME : librpmDb::DbDirInfo
495 //
496 ///////////////////////////////////////////////////////////////////
497
498 ///////////////////////////////////////////////////////////////////
499 //
500 //
501 //      METHOD NAME : librpmDb::DbDirInfo::DbDirInfo
502 //      METHOD TYPE : Constructor
503 //
504 librpmDb::DbDirInfo::DbDirInfo( const Pathname & root_r, const Pathname & dbPath_r )
505     : _root( root_r )
506     , _dbPath( dbPath_r )
507 {
508   // check and adjust arguments
509   if ( ! (root_r.absolute() && dbPath_r.absolute()) )
510   {
511     ERR << "Relative path for root(" << _root << ") or dbPath(" << _dbPath << ")" << endl;
512   }
513   else
514   {
515     _dbDir   ( _root + _dbPath );
516     _dbV4    ( _dbDir.path() + "Packages" );
517     _dbV3    ( _dbDir.path() + "packages.rpm" );
518     _dbV3ToV4( _dbDir.path() + "packages.rpm3" );
519     DBG << *this << endl;
520   }
521 }
522
523 ///////////////////////////////////////////////////////////////////
524 //
525 //
526 //      METHOD NAME : librpmDb::DbDirInfo::update
527 //      METHOD TYPE : void
528 //
529 void librpmDb::DbDirInfo::restat()
530 {
531   _dbDir();
532   _dbV4();
533   _dbV3();
534   _dbV3ToV4();
535   DBG << *this << endl;
536 }
537
538 /******************************************************************
539 **
540 **
541 **      FUNCTION NAME : operator<<
542 **      FUNCTION TYPE : std::ostream &
543 */
544 std::ostream & operator<<( std::ostream & str, const librpmDb::DbDirInfo & obj )
545 {
546   if ( obj.illegalArgs() )
547   {
548     str << "ILLEGAL: '(" << obj.root() << ")" << obj.dbPath() << "'";
549   }
550   else
551   {
552     str << "'(" << obj.root() << ")" << obj.dbPath() << "':" << endl;
553     str << "  Dir:    " << obj._dbDir << endl;
554     str << "  V4:     " << obj._dbV4 << endl;
555     str << "  V3:     " << obj._dbV3 << endl;
556     str << "  V3ToV4: " << obj._dbV3ToV4;
557   }
558   return str;
559 }
560
561 ///////////////////////////////////////////////////////////////////
562 //
563 //      CLASS NAME : librpmDb::db_const_iterator::D
564 /**
565  *
566  **/
567 class librpmDb::db_const_iterator::D
568 {
569   D & operator=( const D & ); // NO ASSIGNMENT!
570   D ( const D & );            // NO COPY!
571 public:
572
573   librpmDb::constPtr     _dbptr;
574   shared_ptr<RpmException> _dberr;
575
576   RpmHeader::constPtr _hptr;
577   rpmdbMatchIterator   _mi;
578
579   D( librpmDb::constPtr dbptr_r )
580       : _dbptr( dbptr_r )
581       , _mi( 0 )
582   {
583     if ( !_dbptr )
584     {
585       try
586       {
587         librpmDb::dbAccess( _dbptr );
588       }
589       catch (const RpmException & excpt_r)
590       {
591         ZYPP_CAUGHT(excpt_r);
592       }
593       if ( !_dbptr )
594       {
595         WAR << "No database access: " << _dberr << endl;
596       }
597     }
598     else
599     {
600       destroy(); // Checks whether _dbptr still valid
601     }
602   }
603
604   ~D()
605   {
606     if ( _mi )
607     {
608       ::rpmdbFreeIterator( _mi );
609     }
610   }
611
612   /**
613    * Let iterator access a dbindex file. Call @ref advance to access the
614    * 1st element (if present).
615    **/
616   bool create( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
617   {
618     destroy();
619     if ( ! _dbptr )
620       return false;
621     _mi = ::rpmtsInitIterator( _dbptr->_d._ts, rpmTag(rpmtag), keyp, keylen );
622     return _mi;
623   }
624
625   /**
626    * Destroy iterator. Invalidates _dbptr, if database was blocked meanwile.
627    * Always returns false.
628    **/
629   bool destroy()
630   {
631     if ( _mi )
632     {
633       _mi = ::rpmdbFreeIterator( _mi );
634       _hptr = 0;
635     }
636     if ( _dbptr && _dbptr->error() )
637     {
638       _dberr = _dbptr->error();
639       WAR << "Lost database access: " << _dberr << endl;
640       _dbptr = 0;
641     }
642     return false;
643   }
644
645   /**
646    * Advance to the first/next header in iterator. Destroys iterator if
647    * no more headers available.
648    **/
649   bool advance()
650   {
651     if ( !_mi )
652       return false;
653     Header h = ::rpmdbNextIterator( _mi );
654     if ( ! h )
655     {
656       destroy();
657       return false;
658     }
659     _hptr = new RpmHeader( h );
660     return true;
661   }
662
663   /**
664    * Access a dbindex file and advance to the 1st header.
665    **/
666   bool init( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
667   {
668     if ( ! create( rpmtag, keyp, keylen ) )
669       return false;
670     return advance();
671   }
672
673   /**
674    * Create an itertator that contains the database entry located at
675    * off_r, and advance to the 1st header.
676    **/
677   bool set( int off_r )
678   {
679     if ( ! create( RPMDBI_PACKAGES ) )
680       return false;
681 #warning TESTCASE: rpmdbAppendIterator and (non)sequential access?
682 #ifdef RPMFILEITERMAX   // since rpm.4.12
683     ::rpmdbAppendIterator( _mi, (const unsigned *)&off_r, 1 );
684 #else
685     ::rpmdbAppendIterator( _mi, &off_r, 1 );
686 #endif
687     return advance();
688   }
689
690   unsigned offset()
691   {
692     return( _mi ? ::rpmdbGetIteratorOffset( _mi ) : 0 );
693   }
694
695   int size()
696   {
697     if ( !_mi )
698       return 0;
699     int ret = ::rpmdbGetIteratorCount( _mi );
700 #warning TESTCASE: rpmdbGetIteratorCount returns 0 on sequential access?
701     return( ret ? ret : -1 ); // -1: sequential access
702   }
703 };
704
705 ///////////////////////////////////////////////////////////////////
706
707 ///////////////////////////////////////////////////////////////////
708 //
709 //      CLASS NAME : librpmDb::Ptr::db_const_iterator
710 //
711 ///////////////////////////////////////////////////////////////////
712
713 ///////////////////////////////////////////////////////////////////
714 //
715 //
716 //      METHOD NAME : librpmDb::db_const_iterator::db_iterator
717 //      METHOD TYPE : Constructor
718 //
719 librpmDb::db_const_iterator::db_const_iterator( librpmDb::constPtr dbptr_r )
720     : _d( * new D( dbptr_r ) )
721 {
722   findAll();
723 }
724
725 ///////////////////////////////////////////////////////////////////
726 //
727 //
728 //      METHOD NAME : librpmDb::db_const_iterator::~db_const_iterator
729 //      METHOD TYPE : Destructor
730 //
731 librpmDb::db_const_iterator::~db_const_iterator()
732 {
733   delete &_d;
734 }
735
736 ///////////////////////////////////////////////////////////////////
737 //
738 //
739 //      METHOD NAME : librpmDb::db_const_iterator::operator++
740 //      METHOD TYPE : void
741 //
742 void librpmDb::db_const_iterator::operator++()
743 {
744   _d.advance();
745 }
746
747 ///////////////////////////////////////////////////////////////////
748 //
749 //
750 //      METHOD NAME : librpmDb::db_const_iterator::dbHdrNum
751 //      METHOD TYPE : unsigned
752 //
753 unsigned librpmDb::db_const_iterator::dbHdrNum() const
754 {
755   return _d.offset();
756 }
757
758 ///////////////////////////////////////////////////////////////////
759 //
760 //
761 //      METHOD NAME : librpmDb::db_const_iterator::operator*
762 //      METHOD TYPE : const RpmHeader::constPtr &
763 //
764 const RpmHeader::constPtr & librpmDb::db_const_iterator::operator*() const
765 {
766   return _d._hptr;
767 }
768
769 ///////////////////////////////////////////////////////////////////
770 //
771 //
772 //      METHOD NAME : librpmDb::db_const_iterator::dbError
773 //      METHOD TYPE : PMError
774 //
775 shared_ptr<RpmException> librpmDb::db_const_iterator::dbError() const
776 {
777   if ( _d._dbptr )
778     return _d._dbptr->error();
779
780   return _d._dberr;
781 }
782
783 /******************************************************************
784 **
785 **
786 **      FUNCTION NAME : operator<<
787 **      FUNCTION TYPE : ostream &
788 */
789 ostream & operator<<( ostream & str, const librpmDb::db_const_iterator & obj )
790 {
791   str << "db_const_iterator(" << obj._d._dbptr
792   << " Size:" << obj._d.size()
793   << " HdrNum:" << obj._d.offset()
794   << ")";
795   return str;
796 }
797
798 ///////////////////////////////////////////////////////////////////
799 //
800 //
801 //      METHOD NAME : librpmDb::db_const_iterator::findAll
802 //      METHOD TYPE : bool
803 //
804 bool librpmDb::db_const_iterator::findAll()
805 {
806   return _d.init( RPMDBI_PACKAGES );
807 }
808
809 ///////////////////////////////////////////////////////////////////
810 //
811 //
812 //      METHOD NAME : librpmDb::db_const_iterator::findByFile
813 //      METHOD TYPE : bool
814 //
815 bool librpmDb::db_const_iterator::findByFile( const std::string & file_r )
816 {
817   return _d.init( RPMTAG_BASENAMES, file_r.c_str() );
818 }
819
820 ///////////////////////////////////////////////////////////////////
821 //
822 //
823 //      METHOD NAME : librpmDb::db_const_iterator::findByProvides
824 //      METHOD TYPE : bool
825 //
826 bool librpmDb::db_const_iterator::findByProvides( const std::string & tag_r )
827 {
828   return _d.init( RPMTAG_PROVIDENAME, tag_r.c_str() );
829 }
830
831 ///////////////////////////////////////////////////////////////////
832 //
833 //
834 //      METHOD NAME : librpmDb::db_const_iterator::findByRequiredBy
835 //      METHOD TYPE : bool
836 //
837 bool librpmDb::db_const_iterator::findByRequiredBy( const std::string & tag_r )
838 {
839   return _d.init( RPMTAG_REQUIRENAME, tag_r.c_str() );
840 }
841
842 ///////////////////////////////////////////////////////////////////
843 //
844 //
845 //      METHOD NAME : librpmDb::db_const_iterator::findByConflicts
846 //      METHOD TYPE : bool
847 //
848 bool librpmDb::db_const_iterator::findByConflicts( const std::string & tag_r )
849 {
850   return _d.init( RPMTAG_CONFLICTNAME, tag_r.c_str() );
851 }
852
853 ///////////////////////////////////////////////////////////////////
854 //
855 //
856 //      METHOD NAME : librpmDb::findByName
857 //      METHOD TYPE : bool
858 //
859 bool librpmDb::db_const_iterator::findByName( const string & name_r )
860 {
861   return _d.init( RPMTAG_NAME, name_r.c_str() );
862 }
863
864 ///////////////////////////////////////////////////////////////////
865 //
866 //
867 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
868 //      METHOD TYPE : bool
869 //
870 bool librpmDb::db_const_iterator::findPackage( const string & name_r )
871 {
872   if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
873     return false;
874
875   if ( _d.size() == 1 )
876     return true;
877
878   // check installtime on multiple entries
879   int match    = 0;
880   time_t itime = 0;
881   for ( ; operator*(); operator++() )
882   {
883     if ( operator*()->tag_installtime() > itime )
884     {
885       match = _d.offset();
886       itime = operator*()->tag_installtime();
887     }
888   }
889
890   return _d.set( match );
891 }
892
893 ///////////////////////////////////////////////////////////////////
894 //
895 //
896 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
897 //      METHOD TYPE : bool
898 //
899 bool librpmDb::db_const_iterator::findPackage( const std::string & name_r, const Edition & ed_r )
900 {
901   if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
902     return false;
903
904   for ( ; operator*(); operator++() )
905   {
906     if ( ed_r == operator*()->tag_edition() )
907     {
908       int match = _d.offset();
909       return _d.set( match );
910     }
911   }
912
913   return _d.destroy();
914 }
915
916 ///////////////////////////////////////////////////////////////////
917 //
918 //
919 //      METHOD NAME : librpmDb::db_const_iterator::findPackage
920 //      METHOD TYPE : bool
921 //
922 bool librpmDb::db_const_iterator::findPackage( const Package::constPtr & which_r )
923 {
924   if ( ! which_r )
925     return _d.destroy();
926
927   return findPackage( which_r->name(), which_r->edition() );
928 }
929
930 } // namespace rpm
931 } // namespace target
932 } // namespace zypp