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