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