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