libzypp 17.35.11
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>
23
24#undef ZYPP_BASE_LOGGER_LOGGROUP
25#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb"
26
27using std::endl;
28
29namespace zypp
30{
31namespace target
32{
33namespace rpm
34{
35 namespace internal
36 {
37 // helper functions here expect basic checks on arguments have been performed.
38 // (globalInit done, root is absolute, dbpath not empty, ...)
39 inline const Pathname & rpmDefaultDbPath()
40 {
41 static const Pathname _val = [](){
42 Pathname ret = librpmDb::expand( "%{_dbpath}" );
43 if ( ret.empty() ) {
44 ret = "/usr/lib/sysimage/rpm";
45 WAR << "Looks like rpm has no %{_dbpath} set!?! Assuming " << ret << endl;
46 }
47 return ret;
48 }();
49 return _val;
50 }
51
52 inline Pathname suggestedDbPath( const Pathname & root_r )
53 {
54 if ( PathInfo( root_r ).isDir() ) {
55 // If a known dbpath exsists, we continue to use it
56 for ( auto p : { "/var/lib/rpm", "/usr/lib/sysimage/rpm" } ) {
57 if ( PathInfo( root_r/p, PathInfo::LSTAT ).isDir() ) {
58 MIL << "Suggest existing database at " << dumpPath( root_r, p ) << endl;
59 return p;
60 }
61 }
62 }
63 const Pathname & defaultDbPath { rpmDefaultDbPath() };
64 MIL << "Suggest rpm dbpath " << dumpPath( root_r, defaultDbPath ) << endl;
65 return defaultDbPath;
66 }
67
68 inline Pathname sanitizedDbPath( const Pathname & root_r, const Pathname & dbPath_r )
69 { return dbPath_r.empty() ? suggestedDbPath( root_r ) : dbPath_r; }
70
71 inline bool dbExists( const Pathname & root_r, const Pathname & dbPath_r )
72 {
73 Pathname dbdir { root_r / sanitizedDbPath( root_r, dbPath_r ) };
74 return PathInfo(dbdir).isDir() && ( PathInfo(dbdir/"Packages").isFile() || PathInfo(dbdir/"Packages.db").isFile() );
75 }
76
77 } // namespace internal
78
80//
81// CLASS NAME : librpmDb (ststic interface)
82//
84
86//
87// CLASS NAME : librpmDb::D
92{
93 D ( const D & ) = delete; // NO COPY!
94 D & operator=( const D & ) = delete; // NO ASSIGNMENT!
95 D(D &&) = delete;
96 D &operator=(D &&) = delete;
97public:
98
99 const Pathname _root; // root directory for all operations
100 const Pathname _dbPath; // directory (below root) that contains the rpmdb
101 AutoDispose<rpmts> _ts; // transaction handle, includes database
102
103 friend std::ostream & operator<<( std::ostream & str, const D & obj )
104 { return str << "{" << dumpPath( obj._root, obj._dbPath ) << "}"; }
105
106 D( Pathname root_r, Pathname dbPath_r, bool readonly_r )
107 : _root { std::move(root_r) }
108 , _dbPath { std::move(dbPath_r) }
109 , _ts { nullptr }
110 {
111 _ts = AutoDispose<rpmts>( ::rpmtsCreate(), ::rpmtsFree );
112 ::rpmtsSetRootDir( _ts, _root.c_str() );
113
114 // open database (creates a missing one on the fly)
115 OnScopeExit cleanup;
117 // temp set %{_dbpath} macro for rpmtsOpenDB
118 cleanup.setDispose( &macroResetDbpath );
120 }
121 int res = ::rpmtsOpenDB( _ts, (readonly_r ? O_RDONLY : O_RDWR ) );
122 if ( res ) {
123 ERR << "rpmdbOpen error(" << res << "): " << *this << endl;
125 }
126 }
127
128private:
129 static void macroSetDbpath( const Pathname & dppath_r )
130 { ::addMacro( NULL, "_dbpath", NULL, dppath_r.asString().c_str(), RMIL_CMDLINE ); }
131
134};
135
137
139{
140 static bool initialized = false;
141
142 if ( initialized )
143 return true;
144
145 int rc = ::rpmReadConfigFiles( NULL, NULL );
146 if ( rc )
147 {
148 ERR << "rpmReadConfigFiles returned " << rc << endl;
149 return false;
150 }
151
152 initialized = true; // Necessary to be able to use exand() in rpmDefaultDbPath().
153 const Pathname & rpmDefaultDbPath { internal::rpmDefaultDbPath() }; // init rpmDefaultDbPath()!
154 MIL << "librpm init done: (_target:" << expand( "%{_target}" ) << ") (_dbpath:" << rpmDefaultDbPath << ")" << endl;
155 return initialized;
156}
157
158std::string librpmDb::expand( const std::string & macro_r )
159{
160 if ( ! globalInit() )
161 return macro_r; // unexpanded
162
163 AutoFREE<char> val = ::rpmExpand( macro_r.c_str(), NULL );
164 if ( val )
165 return std::string( val );
166
167 return std::string();
168}
169
171{
172 if ( ! root_r.absolute() )
173 ZYPP_THROW(RpmInvalidRootException( root_r, "" ));
174
175 // initialize librpm (for rpmDefaultDbPath)
176 if ( ! globalInit() )
178
179 return internal::suggestedDbPath( root_r );
180}
181
182bool librpmDb::dbExists( const Pathname & root_r, const Pathname & dbPath_r )
183{
184 if ( ! root_r.absolute() )
185 ZYPP_THROW(RpmInvalidRootException( root_r, "" ));
186
187 // initialize librpm (for rpmDefaultDbPath)
188 if ( ! globalInit() )
190
191 return internal::dbExists( root_r, dbPath_r );
192}
193
194librpmDb::constPtr librpmDb::dbOpenIf( const Pathname & root_r, const Pathname & dbPath_r )
195{ return dbAccess( root_r, dbPath_r, /*create_r*/false ); }
196
198{ return dbAccess( root_r, dbPath_r, /*create_r*/true ); }
199
200librpmDb::constPtr librpmDb::dbAccess( const Pathname & root_r, const Pathname & dbPath_rx, bool create_r )
201{
202 if ( ! root_r.absolute() )
203 ZYPP_THROW(RpmInvalidRootException( root_r, "" ));
204
205 // initialize librpm (for rpmDefaultDbPath)
206 if ( ! globalInit() )
208
209 Pathname dbPath { internal::sanitizedDbPath( root_r, dbPath_rx ) };
210 bool dbExists = internal::dbExists( root_r, dbPath );
211
212 if ( not create_r && not dbExists ) {
213 WAR << "NoOpen not existing database " << dumpPath( root_r, dbPath ) << endl;
214 return nullptr;
215 }
216 MIL << (dbExists?"Open":"Create") << " database " << dumpPath( root_r, dbPath ) << endl;
217 return new librpmDb( root_r, dbPath, /*readonly*/true );
218}
219
221//
222// CLASS NAME : librpmDb (internal database handle interface (nonstatic))
223//
225
226librpmDb::librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r )
227: _d( * new D( root_r, dbPath_r, readonly_r ) )
228{}
229
231{
232 MIL << "Close database " << *this << endl;
233 delete &_d;
234}
235
236void librpmDb::unref_to( unsigned refCount_r ) const
237{ return; } // if ( refCount_r == 1 ) { tbd if we hold a static reference as weak ptr. }
238
240{ return _d._root; }
241
243{ return _d._dbPath; }
244
245std::ostream & librpmDb::dumpOn( std::ostream & str ) const
246{ return ReferenceCounted::dumpOn( str ) << _d; }
247
249//
250// CLASS NAME : librpmDb::db_const_iterator::D
251//
253{
254 D & operator=( const D & ) = delete; // NO ASSIGNMENT!
255 D ( const D & ) = delete; // NO COPY!
256 D(D &&);
257 D &operator=(D &&) = delete;
258
259public:
260
264
267 {}
268
270 D( const Pathname & root_r, const Pathname & dbPath_r = Pathname() )
271 {
272 try {
273 _dbptr = librpmDb::dbOpenIf( root_r, dbPath_r );
274 }
275 catch ( const RpmException & excpt_r ) {
276 ZYPP_CAUGHT(excpt_r);
277 }
278 if ( not _dbptr ) {
279 WAR << "No database access: " << dumpPath( root_r, dbPath_r ) << endl;
280 }
281 }
282
287 bool create( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
288 {
289 destroy();
290 if ( ! _dbptr )
291 return false;
292 _mi = AutoDispose<rpmdbMatchIterator>( ::rpmtsInitIterator( _dbptr->_d._ts, rpmTag(rpmtag), keyp, keylen ), ::rpmdbFreeIterator );
293 return _mi;
294 }
295
299 bool destroy()
300 {
301 _mi.reset();
302 _hptr.reset();
303 return false;
304 }
305
310 bool advance()
311 {
312 if ( !_mi )
313 return false;
314 Header h = ::rpmdbNextIterator( _mi );
315 if ( ! h )
316 {
317 destroy();
318 return false;
319 }
320 _hptr = new RpmHeader( h );
321 return true;
322 }
323
327 bool init( int rpmtag, const void * keyp = NULL, size_t keylen = 0 )
328 {
329 if ( ! create( rpmtag, keyp, keylen ) )
330 return false;
331 return advance();
332 }
333
338 bool set( int off_r )
339 {
340 if ( ! create( RPMDBI_PACKAGES ) )
341 return false;
342#ifdef RPMFILEITERMAX // since rpm.4.12
343 ::rpmdbAppendIterator( _mi, (const unsigned *)&off_r, 1 );
344#else
345 ::rpmdbAppendIterator( _mi, &off_r, 1 );
346#endif
347 return advance();
348 }
349
350 unsigned offset()
351 {
352 return( _mi ? ::rpmdbGetIteratorOffset( _mi ) : 0 );
353 }
354
355 int size()
356 {
357 if ( !_mi )
358 return 0;
359 int ret = ::rpmdbGetIteratorCount( _mi );
360 return( ret ? ret : -1 ); // -1: sequential access
361 }
362};
363
365
367//
368// CLASS NAME : librpmDb::Ptr::db_const_iterator
369//
371
372#if LEGACY(1735)
373// Former ZYPP_API used this as default ctor (dbptr_r == nullptr).
374// (dbptr_r!=nullptr) is not possible because librpmDb is not in ZYPP_API.
376: db_const_iterator( "/" )
377{}
378#endif
379
383
385: _d( * new D( root_r ) )
386{ findAll(); }
387
389: _d( * new D( root_r, dbPath_r ) )
390{ findAll(); }
391
393: _d( * new D() )
394{}
395
398
400{ return bool(_d._dbptr); }
401
404
406{ return _d.offset(); }
407
410
411std::ostream & operator<<( std::ostream & str, const librpmDb::db_const_iterator & obj )
412{ return str << "db_const_iterator(" << obj._d._dbptr << ")"; }
413
415{ return _d.init( RPMDBI_PACKAGES ); }
416
417bool librpmDb::db_const_iterator::findByFile( const std::string & file_r )
418{ return _d.init( RPMTAG_BASENAMES, file_r.c_str() ); }
419
420bool librpmDb::db_const_iterator::findByProvides( const std::string & tag_r )
421{ return _d.init( RPMTAG_PROVIDENAME, tag_r.c_str() ); }
422
423bool librpmDb::db_const_iterator::findByRequiredBy( const std::string & tag_r )
424{ return _d.init( RPMTAG_REQUIRENAME, tag_r.c_str() ); }
425
426bool librpmDb::db_const_iterator::findByConflicts( const std::string & tag_r )
427{ return _d.init( RPMTAG_CONFLICTNAME, tag_r.c_str() ); }
428
429bool librpmDb::db_const_iterator::findByName( const std::string & name_r )
430{ return _d.init( RPMTAG_NAME, name_r.c_str() ); }
431
432bool librpmDb::db_const_iterator::findPackage( const std::string & name_r )
433{
434 if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
435 return false;
436
437 if ( _d.size() == 1 )
438 return true;
439
440 // check installtime on multiple entries
441 int match = 0;
442 time_t itime = 0;
443 for ( ; operator*(); operator++() )
444 {
445 if ( operator*()->tag_installtime() > itime )
446 {
447 match = _d.offset();
448 itime = operator*()->tag_installtime();
449 }
450 }
451
452 return _d.set( match );
453}
454
455bool librpmDb::db_const_iterator::findPackage( const std::string & name_r, const Edition & ed_r )
456{
457 if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) )
458 return false;
459
460 for ( ; operator*(); operator++() )
461 {
462 if ( ed_r == operator*()->tag_edition() )
463 {
464 int match = _d.offset();
465 return _d.set( match );
466 }
467 }
468
469 return _d.destroy();
470}
471
473{
474 if ( ! which_r )
475 return _d.destroy();
476
477 return findPackage( which_r->name(), which_r->edition() );
478}
479
480} // namespace rpm
481} // namespace target
482} // namespace zypp
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
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:39
friend std::ostream & operator<<(std::ostream &str, const ReferenceCounted &obj)
Stream output via dumpOn.
Wrapper class for stat/lstat.
Definition PathInfo.h:222
bool absolute() const
Test for an absolute path.
Definition Pathname.h:118
const char * c_str() const
String representation.
Definition Pathname.h:112
const std::string & asString() const
String representation.
Definition Pathname.h:93
bool empty() const
Test for an empty path.
Definition Pathname.h:116
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:92
friend std::ostream & operator<<(std::ostream &str, const D &obj)
Definition librpmDb.cc:103
D(Pathname root_r, Pathname dbPath_r, bool readonly_r)
Definition librpmDb.cc:106
AutoDispose< rpmts > _ts
Definition librpmDb.cc:101
D & operator=(const D &)=delete
static void macroSetDbpath(const Pathname &dppath_r)
Definition librpmDb.cc:129
bool create(int rpmtag, const void *keyp=NULL, size_t keylen=0)
Let iterator access a dbindex file.
Definition librpmDb.cc:287
D(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Open a specific rpmdb if it exists.
Definition librpmDb.cc:270
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:338
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:327
AutoDispose< rpmdbMatchIterator > _mi
Definition librpmDb.cc:262
bool advance()
Advance to the first/next header in iterator.
Definition librpmDb.cc:310
Subclass to retrieve rpm database content.
Definition librpmDb.h:198
unsigned dbHdrNum() const
Returns the current headers index in database, 0 if no header.
Definition librpmDb.cc:405
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
Definition librpmDb.cc:420
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
Definition librpmDb.cc:429
bool findByFile(const std::string &file_r)
Reset to iterate all packages that own a certain file.
Definition librpmDb.cc:417
bool findAll()
Reset to iterate all packages.
Definition librpmDb.cc:414
bool hasDB() const
Whether an underlying rpmdb exists.
Definition librpmDb.cc:399
const RpmHeader::constPtr & operator*() const
Returns the current RpmHeader::constPtr or NULL, if no more entries available.
Definition librpmDb.cc:408
bool findByRequiredBy(const std::string &tag_r)
Reset to iterate all packages that require a certain tag.
Definition librpmDb.cc:423
bool findPackage(const std::string &name_r)
Find package by name.
Definition librpmDb.cc:432
void operator++()
Advance to next RpmHeader::constPtr.
Definition librpmDb.cc:402
bool findByConflicts(const std::string &tag_r)
Reset to iterate all packages that conflict with a certain tag.
Definition librpmDb.cc:426
db_const_iterator() ZYPP_DEPRECATED
Open the default rpmdb below the host system (at /).
Definition librpmDb.cc:380
intrusive_ptr< const librpmDb > constPtr
Definition librpmDb.h:55
const Pathname & dbPath() const
Definition librpmDb.cc:242
const Pathname & root() const
Definition librpmDb.cc:239
static bool globalInit()
Initialize lib librpm (read configfiles etc.).
Definition librpmDb.cc:138
std::ostream & dumpOn(std::ostream &str) const override
Dump debug info.
Definition librpmDb.cc:245
static librpmDb::constPtr dbOpenCreate(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Assert the rpmdb below the system at root_r exists.
Definition librpmDb.cc:197
static std::string expand(const std::string &macro_r)
Definition librpmDb.cc:158
librpmDb(const Pathname &root_r, const Pathname &dbPath_r, bool readonly_r=true)
Private constructor! librpmDb objects are to be created via static interface only.
Definition librpmDb.cc:226
static void dbAccess(librpmDb::Ptr &ptr_r)
INTENTIONALLY UNDEFINED<\B> because of bug in Ptr classes which allows implicit conversion from librp...
static librpmDb::constPtr dbOpenIf(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Open the rpmdb below the system at root_r (if it exists).
Definition librpmDb.cc:194
~librpmDb() override
Destructor.
Definition librpmDb.cc:230
static Pathname suggestedDbPath(const Pathname &root_r)
Definition librpmDb.cc:170
static bool dbExists(const Pathname &root_r, const Pathname &dbPath_r=Pathname())
Definition librpmDb.cc:182
void unref_to(unsigned refCount_r) const override
Trigger from Rep, after refCount was decreased.
Definition librpmDb.cc:236
Definition Arch.h:364
String related utilities and Regular expression matching.
const Pathname & rpmDefaultDbPath()
Definition librpmDb.cc:39
Pathname suggestedDbPath(const Pathname &root_r)
Definition librpmDb.cc:52
Pathname sanitizedDbPath(const Pathname &root_r, const Pathname &dbPath_r)
Definition librpmDb.cc:68
bool dbExists(const Pathname &root_r, const Pathname &dbPath_r)
Definition librpmDb.cc:71
_dumpPath dumpPath(const Pathname &root_r, const Pathname &sub_r)
dumpPath iomaip to dump '(root_r)sub_r' output,
Definition librpmDb.h:42
Easy-to use interface to the ZYPP dependency resolver.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:440
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:424
#define MIL
Definition Logger.h:98
#define ERR
Definition Logger.h:100
#define WAR
Definition Logger.h:99