Imported Upstream version 17.23.5
[platform/upstream/libzypp.git] / zypp / target / rpm / RpmDb.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/RpmDb.h
10  *
11 */
12
13 // -*- C++ -*-
14
15 #ifndef ZYPP_TARGET_RPM_RPMDB_H
16 #define ZYPP_TARGET_RPM_RPMDB_H
17
18 #include <iosfwd>
19 #include <list>
20 #include <vector>
21 #include <string>
22
23 #include <zypp/Pathname.h>
24 #include <zypp/ExternalProgram.h>
25
26 #include <zypp/Package.h>
27 #include <zypp/KeyRing.h>
28
29 #include <zypp/target/rpm/RpmFlags.h>
30 #include <zypp/target/rpm/RpmHeader.h>
31 #include <zypp/target/rpm/RpmCallbacks.h>
32 #include <zypp/ZYppCallbacks.h>
33
34 namespace zypp
35 {
36 namespace target
37 {
38 namespace rpm
39 {
40
41 ///////////////////////////////////////////////////////////////////
42 //
43 //      CLASS NAME : RpmDb
44 /**
45  * @short Interface to the rpm program
46  **/
47 class RpmDb : public base::ReferenceCounted, private base::NonCopyable
48 {
49 public:
50
51   /**
52    * Default error class
53    **/
54   typedef class InstTargetError Error;
55
56   ///////////////////////////////////////////////////////////////////
57   //
58   // INITALISATION
59   //
60   ///////////////////////////////////////////////////////////////////
61 private:
62 #if LEGACY(1712)
63   enum DbStateInfoBits {
64     DbSI_NO_INIT        = 0x0000
65   };
66   DbStateInfoBits _dbStateInfo;
67 #endif
68
69   /**
70    * Root directory for all operations.
71    **/
72   Pathname _root;
73
74   /**
75    * Directory that contains the rpmdb.
76    **/
77   Pathname _dbPath;
78
79 public:
80
81   /**
82    * Constructor. There's no rpmdb access until @ref initDatabase
83    * was called.
84    **/
85   RpmDb();
86
87   /**
88    * Destructor.
89    **/
90   ~RpmDb();
91
92   /**
93    * @return Root directory for all operations (empty if not initialized).
94    **/
95   const Pathname & root() const
96   {
97     return _root;
98   }
99
100   /**
101    * @return Directory that contains the rpmdb (empty if not initialized).
102    **/
103   const Pathname & dbPath() const
104   {
105     return _dbPath;
106   }
107
108   /**
109    * @return Whether we are initialized.
110    **/
111   bool initialized() const
112   {
113     return( ! _root.empty() );
114   }
115
116   /**
117    * Prepare access to the rpm database at \c/var/lib/rpm.
118    *
119    * An optional argument denotes the root directory for all operations. If
120    * an empty Pathname is given the default (\c/) is used.
121    *
122    * Calling initDatabase a second time with different arguments will return
123    * an error but leave the database in it's original state.
124    *
125    * If the  database already exists and \c doRebuild_r is true,
126    * \ref rebuildDatabase is called.
127    *
128    * \throws RpmException
129    **/
130   void initDatabase( Pathname root_r = Pathname(), bool doRebuild_r = false );
131
132   /**
133    * Block further access to the rpm database and go back to uninitialized
134    * state. On update: Decides what to do with any converted database
135    * (see @ref initDatabase).
136    *
137    * \throws RpmException
138    *
139    **/
140   void closeDatabase();
141
142   /**
143    * Rebuild the rpm database (rpm --rebuilddb).
144    *
145    * \throws RpmException
146    *
147    **/
148   void rebuildDatabase();
149
150   /**
151    * Import ascii armored public key in file pubkey_r.
152    *
153    * \throws RpmException
154    *
155    **/
156   void importPubkey( const PublicKey & pubkey_r );
157
158   /**
159    * Remove a public key from the rpm database
160    *
161    * \throws RpmException
162    *
163    **/
164   void removePubkey( const PublicKey & pubkey_r );
165
166   /**
167    * Return the long ids of all installed public keys.
168    **/
169   std::list<PublicKey> pubkeys() const;
170
171   /**
172    * Return the edition of all installed public keys.
173    **/
174   std::set<Edition> pubkeyEditions() const;
175
176   ///////////////////////////////////////////////////////////////////
177   //
178   // Direct RPM database retrieval via librpm.
179   //
180   ///////////////////////////////////////////////////////////////////
181 public:
182
183   /**
184    * return complete file list for installed package name_r (in FileInfo.filename)
185    * if edition_r != Edition::noedition, check for exact edition
186    * if full==true, fill all attributes of FileInfo
187    **/
188   std::list<FileInfo> fileList( const std::string & name_r, const Edition & edition_r ) const;
189
190   /**
191    * Return true if at least one package owns a certain file (name_r empty)
192    * Return true if package name_r owns file file_r (name_r nonempty).
193    **/
194   bool hasFile( const std::string & file_r, const std::string & name_r = "" ) const;
195
196   /**
197    * Return name of package owning file
198    * or empty string if no installed package owns file
199    **/
200   std::string whoOwnsFile( const std::string & file_r ) const;
201
202   /**
203    * Return true if at least one package provides a certain tag.
204    **/
205   bool hasProvides( const std::string & tag_r ) const;
206
207   /**
208    * Return true if at least one package requires a certain tag.
209    **/
210   bool hasRequiredBy( const std::string & tag_r ) const;
211
212   /**
213    * Return true if at least one package conflicts with a certain tag.
214    **/
215   bool hasConflicts( const std::string & tag_r ) const;
216
217   /**
218    * Return true if package is installed.
219    **/
220   bool hasPackage( const std::string & name_r ) const;
221
222   /**
223    * Return true if package is installed in a certain edition.
224    **/
225   bool hasPackage( const std::string & name_r, const Edition & ed_r ) const;
226
227   /**
228    * Get an installed packages data from rpmdb. Package is
229    * identified by name. Data returned via result are NULL,
230    * if packge is not installed (PMError is not set), or RPM database
231    * could not be read (PMError is set).
232    *
233    * \throws RpmException
234    *
235    * FIXME this and following comment
236    *
237    **/
238   void getData( const std::string & name_r,
239                 RpmHeader::constPtr & result_r ) const;
240
241   /**
242    * Get an installed packages data from rpmdb. Package is
243    * identified by name and edition. Data returned via result are NULL,
244    * if packge is not installed (PMError is not set), or RPM database
245    * could not be read (PMError is set).
246    *
247    * \throws RpmException
248    *
249    **/
250   void getData( const std::string & name_r, const Edition & ed_r,
251                 RpmHeader::constPtr & result_r ) const;
252
253   ///////////////////////////////////////////////////////////////////
254   //
255   ///////////////////////////////////////////////////////////////////
256 public:
257   /** Sync mode for \ref syncTrustedKeys */
258   enum SyncTrustedKeyBits
259   {
260     SYNC_TO_KEYRING     = 1<<0, //!< export rpm trusted keys into zypp trusted keyring
261     SYNC_FROM_KEYRING   = 1<<1, //!< import zypp trusted keys into rpm database.
262     SYNC_BOTH           = SYNC_TO_KEYRING | SYNC_FROM_KEYRING
263   };
264   /**
265    * Sync trusted keys stored in rpm database and zypp trusted keyring.
266    */
267   void syncTrustedKeys( SyncTrustedKeyBits mode_r = SYNC_BOTH );
268   /**
269    * iterates through zypp keyring and import all non existant keys
270    * into rpm keyring
271    */
272   void importZyppKeyRingTrustedKeys();
273   /**
274    * insert all rpm trusted keys into zypp trusted keyring
275    */
276   void exportTrustedKeysInZyppKeyRing();
277
278 private:
279   /**
280    * The connection to the rpm process.
281   */
282   ExternalProgram *process;
283
284   typedef std::vector<const char*> RpmArgVec;
285
286   /**
287    * Run rpm with the specified arguments and handle stderr.
288    * @param n_opts The number of arguments
289    * @param options Array of the arguments, @ref n_opts elements
290    * @param stderr_disp How to handle stderr, merged with stdout by default
291    *
292    * \throws RpmException
293    *
294    **/
295   void run_rpm( const RpmArgVec& options,
296                 ExternalProgram::Stderr_Disposition stderr_disp =
297                   ExternalProgram::Stderr_To_Stdout);
298
299
300   /**
301    * Read a line from the general rpm query
302   */
303   bool systemReadLine(std::string &line);
304
305   /**
306    * Return the exit status of the general rpm process,
307    * closing the connection if not already done.
308   */
309   int systemStatus();
310
311   /**
312    * Forcably kill the system process
313   */
314   void systemKill();
315
316   /**
317    * The exit code of the rpm process, or -1 if not yet known.
318   */
319   int exit_code;
320
321   /**
322    * Error message from running rpm as external program.
323    * Use only if something fail.
324    */
325   std::string error_message;
326
327   /** /var/adm/backup */
328   Pathname _backuppath;
329
330   /** create package backups? */
331   bool _packagebackups;
332
333 #if LEGACY(1712)
334   /** whether <_root>/<WARNINGMAILPATH> was already created */
335   bool _warndirexists;
336 #endif
337   /**
338    * handle rpm messages like "/etc/testrc saved as /etc/testrc.rpmorig"
339    *
340    * @param line rpm output starting with warning:
341    * @param name name of package, appears in subject line
342    * @param typemsg " saved as " or " created as "
343    * @param difffailmsg what to put into mail if diff failed, must contain two %s for the two files
344    * @param diffgenmsg what to put into mail if diff succeeded, must contain two %s for the two files
345    * */
346   void processConfigFiles(const std::string& line,
347                           const std::string& name,
348                           const char* typemsg,
349                           const char* difffailmsg,
350                           const char* diffgenmsg);
351
352
353 public:
354
355   typedef std::set<std::string> FileList;
356
357   /**
358    * checkPackage result
359    * @see checkPackage
360    * */
361   enum CheckPackageResult
362   {
363     CHK_OK            = 0, /*!< Signature is OK. */
364     CHK_NOTFOUND      = 1, /*!< Signature is unknown type. */
365     CHK_FAIL          = 2, /*!< Signature does not verify. */
366     CHK_NOTTRUSTED    = 3, /*!< Signature is OK, but key is not trusted. */
367     CHK_NOKEY         = 4, /*!< Public key is unavailable. */
368     CHK_ERROR         = 5, /*!< File does not exist or can't be opened. */
369     CHK_NOSIG         = 6, /*!< File has no gpg signature (only digests). */
370   };
371
372   /** Detailed rpm signature check log messages
373    * A single multiline message if \ref CHK_OK. Otherwise each message line
374    * together with it's \ref CheckPackageResult.
375    */
376   struct CheckPackageDetail : std::vector<std::pair<CheckPackageResult,std::string>>
377   {};
378
379   /**
380    * Check signature of rpm file on disk (legacy version returning CHK_OK if file is unsigned, like 'rpm -K')
381    *
382    * @param path_r which file to check
383    * @param detail_r Return detailed rpm log messages
384    *
385    * @return CheckPackageResult (CHK_OK if file is unsigned)
386    *
387    * \see also \ref checkPackageSignature
388    */
389   CheckPackageResult checkPackage( const Pathname & path_r, CheckPackageDetail & detail_r );
390   /** \overload Ignoring the \a details_r */
391   CheckPackageResult checkPackage( const Pathname & path_r );
392
393   /**
394    * Check signature of rpm file on disk (strict check returning CHK_NOSIG if file is unsigned).
395    *
396    * @param path_r which file to check
397    * @param detail_r Return detailed rpm log messages
398    *
399    * @return CheckPackageResult (CHK_NOSIG if file is unsigned)
400    *
401    * \see also \ref checkPackage
402    */
403   CheckPackageResult checkPackageSignature( const Pathname & path_r, CheckPackageDetail & detail_r );
404
405   /** install rpm package
406    *
407    * @param filename file to install
408    * @param flags which rpm options to use
409    *
410    * @return success
411    *
412    * \throws RpmException
413    *
414    * */
415   void installPackage ( const Pathname & filename, RpmInstFlags flags = RPMINST_NONE );
416
417   /** remove rpm package
418    *
419    * @param name_r Name of the rpm package to remove.
420    * @param iflags which rpm options to use
421    *
422    * @return success
423    *
424    * \throws RpmException
425    *
426    * */
427   void removePackage( const std::string & name_r, RpmInstFlags flags = RPMINST_NONE );
428   void removePackage( Package::constPtr package, RpmInstFlags flags = RPMINST_NONE );
429
430   /**
431    * get backup dir for rpm config files
432    *
433    * */
434   Pathname getBackupPath (void)
435   {
436     return _backuppath;
437   }
438
439   /**
440    * create tar.gz of all changed files in a Package
441    *
442    * @param packageName name of the Package to backup
443    *
444    * @see setBackupPath
445    * */
446   bool backupPackage(const std::string& packageName);
447
448   /**
449    * queries file for name and then calls above backupPackage
450    * function. For convenience.
451    *
452    * @param filename rpm file that is about to be installed
453    * */
454   bool backupPackage(const Pathname& filename);
455
456   /**
457    * set path where package backups are stored
458    *
459    * @see backupPackage
460    * */
461   void setBackupPath(const Pathname& path);
462
463   /**
464    * whether to create package backups during install or
465    * removal
466    *
467    * @param yes true or false
468    * */
469   void createPackageBackups(bool yes)
470   {
471     _packagebackups = yes;
472   }
473
474   /**
475    * determine which files of an installed package have been
476    * modified.
477    *
478    * @param fileList (output) where to store modified files
479    * @param packageName name of package to query
480    *
481    * @return false if package couln't be queried for some
482    * reason
483    * */
484   bool queryChangedFiles(FileList & fileList, const std::string& packageName);
485
486 public:
487
488   /**
489    * Dump debug info.
490    **/
491   virtual std::ostream & dumpOn( std::ostream & str ) const;
492
493 protected:
494   void doRemovePackage( const std::string & name_r, RpmInstFlags flags, callback::SendReport<RpmRemoveReport> & report );
495   void doInstallPackage( const Pathname & filename, RpmInstFlags flags, callback::SendReport<RpmInstallReport> & report );
496   void doRebuildDatabase(callback::SendReport<RebuildDBReport> & report);
497 };
498
499 /** \relates RpmDb::CheckPackageResult Stream output */
500 std::ostream & operator<<( std::ostream & str, RpmDb::CheckPackageResult obj );
501
502 /** \relates RpmDb::checkPackageDetail Stream output */
503 std::ostream & operator<<( std::ostream & str, const RpmDb::CheckPackageDetail & obj );
504
505 } // namespace rpm
506 } // namespace target
507 } // namespace zypp
508
509 #endif // ZYPP_TARGET_RPM_RPMDB_H