libzypp 17.32.2
librpmDb.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include "librpm.h"
13
14#include <iostream>
15#include <utility>
16
17#include <zypp/base/Logger.h>
18#include <zypp/PathInfo.h>
22
23#undef ZYPP_BASE_LOGGER_LOGGROUP
24#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
25
26using std::endl;
27
28namespace zypp
29{
30namespace target
31{
32namespace rpm
33{
35//
36// CLASS NAME : librpmDb::D
41{
42 D ( const D & ) = delete; // NO COPY!
43 D & operator=( const D & ) = delete; // NO ASSIGNMENT!
44 D(D &&) = delete;
45 D &operator=(D &&) = delete;
46public:
47
48 const Pathname _root; // root directory for all operations
49 const Pathname _dbPath; // directory (below root) that contains the rpmdb
50 rpmts _ts; // transaction handle, includes database
52
53 friend std::ostream & operator<<( std::ostream & str, const D & obj )
54 {
55 str << "{" << obj._error << "(" << obj._root << ")" << obj._dbPath << "}";
56 return str;
57 }
58
60 : _root(std::move(root_r)), _dbPath(std::move(dbPath_r)), _ts(0) {
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 // open database (creates a missing one on the fly)
69 int res = ::rpmtsOpenDB( _ts, (readonly_r ? O_RDONLY : O_RDWR ));
70 if ( res )
71 {
72 ERR << "rpmdbOpen error(" << res << "): " << *this << endl;
76 return;
77 }
78
79 DBG << "DBACCESS " << *this << endl;
80 }
81
83 {
84 if ( _ts )
85 {
86 ::rpmtsFree(_ts);
87 }
88 }
89};
90
92
94//
95// CLASS NAME : librpmDb (ststic interface)
96//
98
100Pathname librpmDb::_defaultDbPath; // set in dbAccess depending on suggestedDbPath below /root
101Pathname librpmDb::_rpmDefaultDbPath; // set by globalInit
103bool librpmDb::_dbBlocked = true;
104
106//
107//
108// METHOD NAME : librpmDb::globalInit
109// METHOD TYPE : bool
110//
112{
113 static bool initialized = false;
114
115 if ( initialized )
116 return true;
117
118 int rc = ::rpmReadConfigFiles( NULL, NULL );
119 if ( rc )
120 {
121 ERR << "rpmReadConfigFiles returned " << rc << endl;
122 return false;
123 }
124
125 initialized = true; // Necessary to be able to use exand().
126 _rpmDefaultDbPath = expand( "%{_dbpath}" );
127
128 if ( _rpmDefaultDbPath.empty() ) {
129 _rpmDefaultDbPath = "/usr/lib/sysimage/";
130 WAR << "Looks like rpm has no %{_dbpath} set!?! Assuming " << _rpmDefaultDbPath << endl;
131 }
132 MIL << "librpm init done: (_target:" << expand( "%{_target}" ) << ") (_dbpath:" << _rpmDefaultDbPath << ")" << endl;
133 return initialized;
134}
135
137//
138//
139// METHOD NAME : librpmDb::expand
140// METHOD TYPE : std::string
141//
142std::string librpmDb::expand( const std::string & macro_r )
143{
144 if ( ! globalInit() )
145 return macro_r; // unexpanded
146
147 char * val = ::rpmExpand( macro_r.c_str(), NULL );
148 if ( !val )
149 return "";
150
151 std::string ret( val );
152 free( val );
153 return ret;
154}
155
157//
158//
159// METHOD NAME : librpmDb::newLibrpmDb
160// METHOD TYPE : librpmDb *
161//
163{
164 // initialize librpm
165 if ( ! globalInit() )
166 {
168 }
169
170 if ( _defaultDbPath.empty() ) // db_const_iterator access to /(default) without RpmDB/Tareget init.
172
173 // open rpmdb
174 librpmDb * ret = 0;
175 try
176 {
177 ret = new librpmDb( _defaultRoot, _defaultDbPath, /*readonly*/true );
178 }
179 catch (const RpmException & excpt_r)
180 {
182 delete ret;
183 ret = 0;
185 }
186 return ret;
187}
188
189
191{
192 if ( ! root_r.absolute() )
194
195 // initialize librpm (for _rpmDefaultDbPath)
196 if ( ! globalInit() )
198
199 if ( PathInfo( root_r ).isDir() ) {
200 // If a known dbpath exsists, we continue to use it
201 for ( auto p : { "/var/lib/rpm", "/usr/lib/sysimage/rpm" } ) {
202 if ( PathInfo( root_r/p, PathInfo::LSTAT ).isDir() ) {
203 MIL << "Suggest existing database at " << stringPath( root_r, p ) << endl;
204 return p;
205 }
206 }
207 }
208
209 MIL << "Suggest rpm _dbpath " << stringPath( root_r, _rpmDefaultDbPath ) << endl;
210 return _rpmDefaultDbPath;
211}
212
214//
215//
216// METHOD NAME : librpmDb::dbAccess
217// METHOD TYPE : PMError
218//
220{
221 if ( _defaultDb )
222 {
223 // already accessing a database: switching is not allowed.
224 if ( _defaultRoot == root_r )
225 return;
226 else
228 }
229
230 // got no database: we could switch to a new one (even if blocked!)
231 _defaultDbPath = suggestedDbPath( root_r ); // also asserts root_r is absolute
233
234 MIL << "Set new database location: " << stringPath( _defaultRoot, _defaultDbPath ) << endl;
235 return dbAccess();
236}
237
239//
240//
241// METHOD NAME : librpmDb::dbAccess
242// METHOD TYPE : PMError
243//
245{
246 if ( _dbBlocked )
247 {
249 }
250
251 if ( !_defaultDb )
252 {
253 // get access
255 }
256}
257
259//
260//
261// METHOD NAME : librpmDb::dbAccess
262// METHOD TYPE : PMError
263//
265{
266 ptr_r = nullptr;
267 dbAccess();
269}
270
272//
273//
274// METHOD NAME : librpmDb::dbRelease
275// METHOD TYPE : unsigned
276//
278{
279 if ( !_defaultDb )
280 {
281 return 0;
282 }
283
284 unsigned outstanding = _defaultDb->refCount() - 1; // refCount can't be 0
285
286 switch ( outstanding )
287 {
288 default:
289 if ( !force_r )
290 {
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
300 // tag handle invalid
301 _defaultDb = 0;
302 break;
303 }
304
305 return outstanding;
306}
307
309//
310//
311// METHOD NAME : librpmDb::blockAccess
312// METHOD TYPE : unsigned
313//
315{
316 MIL << "Block access" << endl;
317 _dbBlocked = true;
318 return dbRelease( /*force*/true );
319}
320
322//
323//
324// METHOD NAME : librpmDb::unblockAccess
325// METHOD TYPE : void
326//
328{
329 MIL << "Unblock access" << endl;
330 _dbBlocked = false;
331}
332
334//
335//
336// METHOD NAME : librpmDb::dumpState
337// METHOD TYPE : ostream &
338//
339std::ostream & librpmDb::dumpState( std::ostream & str )
340{
341 if ( !_defaultDb )
342 {
343 return str << "[librpmDb " << (_dbBlocked?"BLOCKED":"CLOSED") << " " << stringPath( _defaultRoot, _defaultDbPath ) << "]";
344 }
345 return str << "[" << _defaultDb << "]";
346}
347
349//
350// CLASS NAME : librpmDb (internal database handle interface (nonstatic))
351//
353
355//
356//
357// METHOD NAME : librpmDb::librpmDb
358// METHOD TYPE : Constructor
359//
360// DESCRIPTION :
361//
363 : _d( * new D( root_r, dbPath_r, readonly_r ) )
364{}
365
367//
368//
369// METHOD NAME : librpmDb::~librpmDb
370// METHOD TYPE : Destructor
371//
372// DESCRIPTION :
373//
375{
376 delete &_d;
377}
378
380//
381//
382// METHOD NAME : librpmDb::unref_to
383// METHOD TYPE : void
384//
385void librpmDb::unref_to( unsigned refCount_r ) const
386{
387 if ( refCount_r == 1 )
388 {
389 dbRelease();
390 }
391}
392
394//
395//
396// METHOD NAME : librpmDb::root
397// METHOD TYPE : const Pathname &
398//
400{
401 return _d._root;
402}
403
405//
406//
407// METHOD NAME : librpmDb::dbPath
408// METHOD TYPE : const Pathname &
409//
411{
412 return _d._dbPath;
413}
414
416//
417//
418// METHOD NAME : librpmDb::error
419// METHOD TYPE : PMError
420//
422{
423 return _d._error;
424}
425
427//
428//
429// METHOD NAME : librpmDb::empty
430// METHOD TYPE : bool
431//
432bool librpmDb::empty() const
433{
434 return( valid() && ! *db_const_iterator( this ) );
435}
436
438//
439//
440// METHOD NAME : librpmDb::size
441// METHOD TYPE : unsigned
442//
443unsigned librpmDb::size() const
444{
445 unsigned count = 0;
446 if ( valid() )
447 {
448 db_const_iterator it( this );
449 for ( db_const_iterator it( this ); *it; ++it )
450 ++count;
451 }
452 return count;
453}
454
456//
457//
458// METHOD NAME : librpmDb::dont_call_it
459// METHOD TYPE : void *
460//
462{
463 return rpmtsGetRdb(_d._ts);
464}
465
467//
468//
469// METHOD NAME : librpmDb::dumpOn
470// METHOD TYPE : ostream &
471//
472// DESCRIPTION :
473//
474std::ostream & librpmDb::dumpOn( std::ostream & str ) const
475{
476 ReferenceCounted::dumpOn( str ) << _d;
477 return str;
478}
479
481//
482// CLASS NAME : librpmDb::db_const_iterator::D
487{
488 D & operator=( const D & ) = delete; // NO ASSIGNMENT!
489 D ( const D & ) = delete; // NO COPY!
490 D(D &&);
491 D &operator=(D &&) = delete;
492public:
493
496
498 rpmdbMatchIterator _mi;
499
501 if ( !_dbptr )
502 {
503 try
504 {
506 }
507 catch (const RpmException & excpt_r)
508 {
510 }
511 if ( !_dbptr )
512 {
513 WAR << "No database access: " << _dberr << endl;
514 }
515 }
516 else
517 {
518 destroy(); // Checks whether _dbptr still valid
519 }
520 }
521
523 {
524 if ( _mi )
525 {
526 ::rpmdbFreeIterator( _mi );
527 }
528 }
529
534 bool create( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
535 {
536 destroy();
537 if ( ! _dbptr )
538 return false;
539 _mi = ::rpmtsInitIterator( _dbptr->_d._ts, rpmTag(rpmtag), keyp, keylen );
540 return _mi;
541 }
542
547 bool destroy()
548 {
549 if ( _mi )
550 {
551 _mi = ::rpmdbFreeIterator( _mi );
552 _hptr = 0;
553 }
554 if ( _dbptr && _dbptr->error() )
555 {
556 _dberr = _dbptr->error();
557 WAR << "Lost database access: " << _dberr << endl;
558 _dbptr = 0;
559 }
560 return false;
561 }
562
567 bool advance()
568 {
569 if ( !_mi )
570 return false;
571 Header h = ::rpmdbNextIterator( _mi );
572 if ( ! h )
573 {
574 destroy();
575 return false;
576 }
577 _hptr = new RpmHeader( h );
578 return true;
579 }
580
584 bool init( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
585 {
586 if ( ! create( rpmtag, keyp, keylen ) )
587 return false;
588 return advance();
589 }
590
595 bool set( int off_r )
596 {
597 if ( ! create( RPMDBI_PACKAGES ) )
598 return false;
599#ifdef RPMFILEITERMAX // since rpm.4.12
600 ::rpmdbAppendIterator( _mi, (const unsigned *)&off_r, 1 );
601#else
602 ::rpmdbAppendIterator( _mi, &off_r, 1 );
603#endif
604 return advance();
605 }
606
607 unsigned offset()
608 {
609 return( _mi ? ::rpmdbGetIteratorOffset( _mi ) : 0 );
610 }
611
612 int size()
613 {
614 if ( !_mi )
615 return 0;
616 int ret = ::rpmdbGetIteratorCount( _mi );
617 return( ret ? ret : -1 ); // -1: sequential access
618 }
619};
620
622
624//
625// CLASS NAME : librpmDb::Ptr::db_const_iterator
626//
628
630//
631//
632// METHOD NAME : librpmDb::db_const_iterator::db_iterator
633// METHOD TYPE : Constructor
634//
640
642//
643//
644// METHOD NAME : librpmDb::db_const_iterator::~db_const_iterator
645// METHOD TYPE : Destructor
646//
651
653//
654//
655// METHOD NAME : librpmDb::db_const_iterator::operator++
656// METHOD TYPE : void
657//
659{
660 _d.advance();
661}
662
664//
665//
666// METHOD NAME : librpmDb::db_const_iterator::dbHdrNum
667// METHOD TYPE : unsigned
668//
670{
671 return _d.offset();
672}
673
675//
676//
677// METHOD NAME : librpmDb::db_const_iterator::operator*
678// METHOD TYPE : const RpmHeader::constPtr &
679//
681{
682 return _d._hptr;
683}
684
686//
687//
688// METHOD NAME : librpmDb::db_const_iterator::dbError
689// METHOD TYPE : PMError
690//
692{
693 if ( _d._dbptr )
694 return _d._dbptr->error();
695
696 return _d._dberr;
697}
698
699/******************************************************************
700**
701**
702** FUNCTION NAME : operator<<
703** FUNCTION TYPE : ostream &
704*/
705std::ostream & operator<<( std::ostream & str, const librpmDb::db_const_iterator & obj )
706{
707 str << "db_const_iterator(" << obj._d._dbptr
708 << " Size:" << obj._d.size()
709 << " HdrNum:" << obj._d.offset()
710 << ")";
711 return str;
712}
713
715//
716//
717// METHOD NAME : librpmDb::db_const_iterator::findAll
718// METHOD TYPE : bool
719//
721{
722 return _d.init( RPMDBI_PACKAGES );
723}
724
726//
727//
728// METHOD NAME : librpmDb::db_const_iterator::findByFile
729// METHOD TYPE : bool
730//
732{
733 return _d.init( RPMTAG_BASENAMES, file_r.c_str() );
734}
735
737//
738//
739// METHOD NAME : librpmDb::db_const_iterator::findByProvides
740// METHOD TYPE : bool
741//
743{
744 return _d.init( RPMTAG_PROVIDENAME, tag_r.c_str() );
745}
746
748//
749//
750// METHOD NAME : librpmDb::db_const_iterator::findByRequiredBy
751// METHOD TYPE : bool
752//
754{
755 return _d.init( RPMTAG_REQUIRENAME, tag_r.c_str() );
756}
757
759//
760//
761// METHOD NAME : librpmDb::db_const_iterator::findByConflicts
762// METHOD TYPE : bool
763//
765{
766 return _d.init( RPMTAG_CONFLICTNAME, tag_r.c_str() );
767}
768
770//
771//
772// METHOD NAME : librpmDb::findByName
773// METHOD TYPE : bool
774//
776{
777 return _d.init( RPMTAG_NAME, name_r.c_str() );
778}
779
781//
782//
783// METHOD NAME : librpmDb::db_const_iterator::findPackage
784// METHOD TYPE : bool
785//
787{
788 if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
789 return false;
790
791 if ( _d.size() == 1 )
792 return true;
793
794 // check installtime on multiple entries
795 int match = 0;
796 time_t itime = 0;
797 for ( ; operator*(); operator++() )
798 {
799 if ( operator*()->tag_installtime() > itime )
800 {
801 match = _d.offset();
802 itime = operator*()->tag_installtime();
803 }
804 }
805
806 return _d.set( match );
807}
808
810//
811//
812// METHOD NAME : librpmDb::db_const_iterator::findPackage
813// METHOD TYPE : bool
814//
816{
817 if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
818 return false;
819
820 for ( ; operator*(); operator++() )
821 {
822 if ( ed_r == operator*()->tag_edition() )
823 {
824 int match = _d.offset();
825 return _d.set( match );
826 }
827 }
828
829 return _d.destroy();
830}
831
833//
834//
835// METHOD NAME : librpmDb::db_const_iterator::findPackage
836// METHOD TYPE : bool
837//
839{
840 if ( ! which_r )
841 return _d.destroy();
842
843 return findPackage( which_r->name(), which_r->edition() );
844}
845
846} // namespace rpm
847} // namespace target
848} // namespace zypp
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
void reset()
Reset to default Ctor values.
Edition represents [epoch:]version[-release]
Definition Edition.h:61
TraitsType::constPtrType constPtr
Definition Package.h:38
friend std::ostream & operator<<(std::ostream &str, const ReferenceCounted &obj)
Stream output via dumpOn.
Wrapper class for stat/lstat.
Definition PathInfo.h:222
const char * c_str() const
String representation.
Definition Pathname.h:110
const std::string & asString() const
String representation.
Definition Pathname.h:91
Just inherits Exception to separate media exceptions.
Wrapper class for rpm header struct.
Definition RpmHeader.h:62
intrusive_ptr< const RpmHeader > constPtr
Definition RpmHeader.h:65
librpmDb internal database handle
Definition librpmDb.cc:41
friend std::ostream & operator<<(std::ostream &str, const D &obj)
Definition librpmDb.cc:53
D(Pathname root_r, Pathname dbPath_r, bool readonly_r)
Definition librpmDb.cc:59
D & operator=(const D &)=delete
shared_ptr< RpmException > _error
Definition librpmDb.cc:51
bool create(int rpmtag, const void *keyp=NULL, size_t keylen=0)
Let iterator access a dbindex file.
Definition librpmDb.cc:534
bool set(int off_r)
Create an itertator that contains the database entry located at off_r, and advance to the 1st header.
Definition librpmDb.cc:595
bool init(int rpmtag, const void *keyp=NULL, size_t keylen=0)
Access a dbindex file and advance to the 1st header.
Definition librpmDb.cc:584
bool advance()
Advance to the first/next header in iterator.
Definition librpmDb.cc:567
Subclass to retrieve database content.
Definition librpmDb.h:344
unsigned dbHdrNum() const
Returns the current headers index in database, 0 if no header.
Definition librpmDb.cc:669
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
Definition librpmDb.cc:742
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
Definition librpmDb.cc:775
bool findByFile(const std::string &file_r)
Reset to iterate all packages that own a certain file.
Definition librpmDb.cc:731
bool findAll()
Reset to iterate all packages.
Definition librpmDb.cc:720
const RpmHeader::constPtr & operator*() const
Returns the current RpmHeader::constPtr or NULL, if no more entries available.
Definition librpmDb.cc:680
bool findByRequiredBy(const std::string &tag_r)
Reset to iterate all packages that require a certain tag.
Definition librpmDb.cc:753
bool findPackage(const std::string &name_r)
Find package by name.
Definition librpmDb.cc:786
shared_ptr< RpmException > dbError() const
Return any database error.
Definition librpmDb.cc:691
void operator++()
Advance to next RpmHeader::constPtr.
Definition librpmDb.cc:658
bool findByConflicts(const std::string &tag_r)
Reset to iterate all packages that conflict with a certain tag.
Definition librpmDb.cc:764
db_const_iterator(const db_const_iterator &)
Manage access to librpm database.
Definition librpmDb.h:38
static bool _dbBlocked
Whether access is blocked (no _defaultDb will be available).
Definition librpmDb.h:87
intrusive_ptr< const librpmDb > constPtr
Definition librpmDb.h:41
const Pathname & dbPath() const
Definition librpmDb.cc:410
const Pathname & root() const
Definition librpmDb.cc:399
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
Definition librpmDb.cc:111
unsigned size() const
Definition librpmDb.cc:443
static std::string stringPath(const Pathname &root_r, const Pathname &sub_r)
Definition librpmDb.h:130
static unsigned dbRelease(bool force_r=false)
If there are no outstanding references to the database (e.g.
Definition librpmDb.cc:277
static std::ostream & dumpState(std::ostream &str)
Dump debug info.
Definition librpmDb.cc:339
static librpmDb::constPtr _defaultDb
Current rpmdb handle.
Definition librpmDb.h:82
shared_ptr< RpmException > error() const
Return any database error.
Definition librpmDb.cc:421
static Pathname _rpmDefaultDbPath
_dbpath configured in rpm config.
Definition librpmDb.h:77
static Pathname _defaultDbPath
Current directory (below root) that contains the rpmdb.
Definition librpmDb.h:72
static librpmDb * newLibrpmDb()
For internal use.
Definition librpmDb.cc:162
std::ostream & dumpOn(std::ostream &str) const override
Dump debug info.
Definition librpmDb.cc:474
void * dont_call_it() const
Dont call it ;) It's for development and testing only.
Definition librpmDb.cc:461
static Pathname _defaultRoot
Current root directory for all operations.
Definition librpmDb.h:67
static std::string expand(const std::string &macro_r)
Definition librpmDb.cc:142
librpmDb(const Pathname &root_r, const Pathname &dbPath_r, bool readonly_r)
Private constructor! librpmDb objects are to be created via static interface only.
Definition librpmDb.cc:362
~librpmDb() override
Destructor.
Definition librpmDb.cc:374
static void dbAccess()
Access the database at the current default location.
Definition librpmDb.cc:244
static unsigned blockAccess()
Blocks further access to rpmdb.
Definition librpmDb.cc:314
static Pathname suggestedDbPath(const Pathname &root_r)
Definition librpmDb.cc:190
void unref_to(unsigned refCount_r) const override
Trigger from Rep, after refCount was decreased.
Definition librpmDb.cc:385
static void unblockAccess()
Allow access to rpmdb e.g.
Definition librpmDb.cc:327
Definition Arch.h:364
String related utilities and Regular expression matching.
Easy-to use interface to the ZYPP dependency resolver.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition Exception.h:441
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:437
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:429
#define DBG
Definition Logger.h:95
#define MIL
Definition Logger.h:96
#define ERR
Definition Logger.h:98
#define WAR
Definition Logger.h:97