Imported Upstream version 15.0.0
[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
63   enum DbStateInfoBits {
64     DbSI_NO_INIT        = 0x0000,
65     DbSI_HAVE_V4        = 0x0001,
66     DbSI_MADE_V4        = 0x0002,
67     DbSI_MODIFIED_V4    = 0x0004,
68     DbSI_HAVE_V3        = 0x0008,
69     DbSI_HAVE_V3TOV4    = 0x0010,
70     DbSI_MADE_V3TOV4    = 0x0020
71   };
72
73   friend std::ostream & operator<<( std::ostream & str, const DbStateInfoBits & obj );
74
75   void dbsi_set( DbStateInfoBits & val_r, const unsigned & bits_r ) const
76   {
77     val_r = (DbStateInfoBits)(val_r | bits_r);
78   }
79   void dbsi_clr( DbStateInfoBits & val_r, const unsigned & bits_r ) const
80   {
81     val_r = (DbStateInfoBits)(val_r & ~bits_r);
82   }
83   bool dbsi_has( const DbStateInfoBits & val_r, const unsigned & bits_r ) const
84   {
85     return( (val_r & bits_r) == bits_r );
86   }
87
88   /**
89    * Internal state info
90    **/
91   DbStateInfoBits _dbStateInfo;
92
93   /**
94    * Root directory for all operations.
95    **/
96   Pathname _root;
97
98   /**
99    * Directory that contains the rpmdb.
100    **/
101   Pathname _dbPath;
102
103   /**
104    * Internal helper for @ref initDatabase.
105    *
106    * \throws RpmException
107    *
108    **/
109   void internal_initDatabase( const Pathname & root_r, const Pathname & dbPath_r,
110                               DbStateInfoBits & info_r );
111
112   /**
113    * Remove the rpm4 database in dbdir_r and optionally any backup created
114    * on conversion.
115    **/
116   static void removeV4( const Pathname & dbdir_r, bool v3backup_r );
117
118   /**
119    * Remove the rpm3 database in dbdir_r. Create a backup copy named
120    * packages.rpm3 if it does not already exist.
121    **/
122   static void removeV3( const Pathname & dbdir_r, bool v3backup_r );
123
124   /**
125    * Called before the database is modified by installPackage/removePackage.
126    * Invalidates Packages list and moves away any old database.
127    **/
128   void modifyDatabase();
129
130 public:
131
132   /**
133    * Constructor. There's no rpmdb access until @ref initDatabase
134    * was called.
135    **/
136   RpmDb();
137
138   /**
139    * Destructor.
140    **/
141   ~RpmDb();
142
143   /**
144    * timestamp of the rpm database (last modification)
145    */
146   Date timestamp() const;
147
148   /**
149    * @return Root directory for all operations (empty if not initialized).
150    **/
151   const Pathname & root() const
152   {
153     return _root;
154   }
155
156   /**
157    * @return Directory that contains the rpmdb (empty if not initialized).
158    **/
159   const Pathname & dbPath() const
160   {
161     return _dbPath;
162   }
163
164   /**
165    * @return Whether we are initialized.
166    **/
167   bool initialized() const
168   {
169     return( ! _root.empty() );
170   }
171
172   /**
173    * Prepare access to the rpm database. Optional arguments may denote the
174    * root directory for all operations and the directory (below root) that
175    * contains the rpmdb (usg. you won't need to set this).
176    *
177    * On empty Pathnames the default is used:
178    * <PRE>
179    *     root:   /
180    *     dbPath: /var/lib/rpm
181    * </PRE>
182    *
183    * Calling initDatabase a second time with different arguments will return
184    * an error but leave the database in it's original state.
185    *
186    * Converting an old batabase is done if necessary. On update: The converted
187    * database will be removed by @ref closeDatabase, if it was not modified
188    * (no packages were installed or deleted). Otherwise the new database
189    * is kept, and the old one is removed.
190    *
191    * If the  database alredy exists and \c doRebuild_r is true, \ref rebuildDatabase
192    * is called.
193    *
194    * \throws RpmException
195    *
196    **/
197   void initDatabase( Pathname root_r = Pathname(),
198                      Pathname dbPath_r = Pathname(),
199                      bool doRebuild_r = false );
200
201   /**
202    * Block further access to the rpm database and go back to uninitialized
203    * state. On update: Decides what to do with any converted database
204    * (see @ref initDatabase).
205    *
206    * \throws RpmException
207    *
208    **/
209   void closeDatabase();
210
211   /**
212    * Rebuild the rpm database (rpm --rebuilddb).
213    *
214    * \throws RpmException
215    *
216    **/
217   void rebuildDatabase();
218
219   /**
220    * Import ascii armored public key in file pubkey_r.
221    *
222    * \throws RpmException
223    *
224    **/
225   void importPubkey( const PublicKey & pubkey_r );
226
227   /**
228    * Remove a public key from the rpm database
229    *
230    * \throws RpmException
231    *
232    **/
233   void removePubkey( const PublicKey & pubkey_r );
234
235   /**
236    * Return the long ids of all installed public keys.
237    **/
238   std::list<PublicKey> pubkeys() const;
239
240   /**
241    * Return the edition of all installed public keys.
242    **/
243   std::set<Edition> pubkeyEditions() const;
244
245   ///////////////////////////////////////////////////////////////////
246   //
247   // Direct RPM database retrieval via librpm.
248   //
249   ///////////////////////////////////////////////////////////////////
250 public:
251
252   /**
253    * return complete file list for installed package name_r (in FileInfo.filename)
254    * if edition_r != Edition::noedition, check for exact edition
255    * if full==true, fill all attributes of FileInfo
256    **/
257   std::list<FileInfo> fileList( const std::string & name_r, const Edition & edition_r ) const;
258
259   /**
260    * Return true if at least one package owns a certain file (name_r empty)
261    * Return true if package name_r owns file file_r (name_r nonempty).
262    **/
263   bool hasFile( const std::string & file_r, const std::string & name_r = "" ) const;
264
265   /**
266    * Return name of package owning file
267    * or empty string if no installed package owns file
268    **/
269   std::string whoOwnsFile( const std::string & file_r ) const;
270
271   /**
272    * Return true if at least one package provides a certain tag.
273    **/
274   bool hasProvides( const std::string & tag_r ) const;
275
276   /**
277    * Return true if at least one package requires a certain tag.
278    **/
279   bool hasRequiredBy( const std::string & tag_r ) const;
280
281   /**
282    * Return true if at least one package conflicts with a certain tag.
283    **/
284   bool hasConflicts( const std::string & tag_r ) const;
285
286   /**
287    * Return true if package is installed.
288    **/
289   bool hasPackage( const std::string & name_r ) const;
290
291   /**
292    * Return true if package is installed in a certain edition.
293    **/
294   bool hasPackage( const std::string & name_r, const Edition & ed_r ) const;
295
296   /**
297    * Get an installed packages data from rpmdb. Package is
298    * identified by name. Data returned via result are NULL,
299    * if packge is not installed (PMError is not set), or RPM database
300    * could not be read (PMError is set).
301    *
302    * \throws RpmException
303    *
304    * FIXME this and following comment
305    *
306    **/
307   void getData( const std::string & name_r,
308                 RpmHeader::constPtr & result_r ) const;
309
310   /**
311    * Get an installed packages data from rpmdb. Package is
312    * identified by name and edition. Data returned via result are NULL,
313    * if packge is not installed (PMError is not set), or RPM database
314    * could not be read (PMError is set).
315    *
316    * \throws RpmException
317    *
318    **/
319   void getData( const std::string & name_r, const Edition & ed_r,
320                 RpmHeader::constPtr & result_r ) const;
321
322   ///////////////////////////////////////////////////////////////////
323   //
324   ///////////////////////////////////////////////////////////////////
325 public:
326   /** Sync mode for \ref syncTrustedKeys */
327   enum SyncTrustedKeyBits
328   {
329     SYNC_TO_KEYRING     = 1<<0, //! export rpm trusted keys into zypp trusted keyring
330     SYNC_FROM_KEYRING   = 1<<1, //! import zypp trusted keys into rpm database.
331     SYNC_BOTH           = SYNC_TO_KEYRING | SYNC_FROM_KEYRING
332   };
333   /**
334    * Sync trusted keys stored in rpm database and zypp trusted keyring.
335    */
336   void syncTrustedKeys( SyncTrustedKeyBits mode_r = SYNC_BOTH );
337   /**
338    * iterates through zypp keyring and import all non existant keys
339    * into rpm keyring
340    */
341   void importZyppKeyRingTrustedKeys();
342   /**
343    * insert all rpm trusted keys into zypp trusted keyring
344    */
345   void exportTrustedKeysInZyppKeyRing();
346
347 private:
348   /**
349    * The connection to the rpm process.
350   */
351   ExternalProgram *process;
352
353   typedef std::vector<const char*> RpmArgVec;
354
355   /**
356    * Run rpm with the specified arguments and handle stderr.
357    * @param n_opts The number of arguments
358    * @param options Array of the arguments, @ref n_opts elements
359    * @param stderr_disp How to handle stderr, merged with stdout by default
360    *
361    * \throws RpmException
362    *
363    **/
364   void run_rpm( const RpmArgVec& options,
365                 ExternalProgram::Stderr_Disposition stderr_disp =
366                   ExternalProgram::Stderr_To_Stdout);
367
368
369   /**
370    * Read a line from the general rpm query
371   */
372   bool systemReadLine(std::string &line);
373
374   /**
375    * Return the exit status of the general rpm process,
376    * closing the connection if not already done.
377   */
378   int systemStatus();
379
380   /**
381    * Forcably kill the system process
382   */
383   void systemKill();
384
385   /**
386    * The exit code of the rpm process, or -1 if not yet known.
387   */
388   int exit_code;
389
390   /**
391    * Error message from running rpm as external program.
392    * Use only if something fail.
393    */
394   std::string error_message;
395
396   /** /var/adm/backup */
397   Pathname _backuppath;
398
399   /** create package backups? */
400   bool _packagebackups;
401
402   /** whether <_root>/<WARNINGMAILPATH> was already created */
403   bool _warndirexists;
404
405   /**
406    * handle rpm messages like "/etc/testrc saved as /etc/testrc.rpmorig"
407    *
408    * @param line rpm output starting with warning:
409    * @param name name of package, appears in subject line
410    * @param typemsg " saved as " or " created as "
411    * @param difffailmsg what to put into mail if diff failed, must contain two %s for the two files
412    * @param diffgenmsg what to put into mail if diff succeeded, must contain two %s for the two files
413    * */
414   void processConfigFiles(const std::string& line,
415                           const std::string& name,
416                           const char* typemsg,
417                           const char* difffailmsg,
418                           const char* diffgenmsg);
419
420
421 public:
422
423   typedef std::set<std::string> FileList;
424
425   /**
426    * checkPackage result
427    * @see checkPackage
428    * */
429   enum checkPackageResult
430   {
431     CHK_OK            = 0, /*!< Signature is OK. */
432     CHK_NOTFOUND      = 1, /*!< Signature is unknown type. */
433     CHK_FAIL          = 2, /*!< Signature does not verify. */
434     CHK_NOTTRUSTED    = 3, /*!< Signature is OK, but key is not trusted. */
435     CHK_NOKEY         = 4, /*!< Public key is unavailable. */
436     CHK_ERROR         = 5  /*!< File does not exist or can't be opened. */
437   };
438
439   /**
440    * Check signature of rpm file on disk.
441    *
442    * @param filename which file to check
443    *
444    * @return checkPackageResult
445   */
446   checkPackageResult checkPackage( const Pathname & path_r );
447
448   /** install rpm package
449    *
450    * @param filename file to install
451    * @param flags which rpm options to use
452    *
453    * @return success
454    *
455    * \throws RpmException
456    *
457    * */
458   void installPackage ( const Pathname & filename, RpmInstFlags flags = RPMINST_NONE );
459
460   /** remove rpm package
461    *
462    * @param name_r Name of the rpm package to remove.
463    * @param iflags which rpm options to use
464    *
465    * @return success
466    *
467    * \throws RpmException
468    *
469    * */
470   void removePackage( const std::string & name_r, RpmInstFlags flags = RPMINST_NONE );
471   void removePackage( Package::constPtr package, RpmInstFlags flags = RPMINST_NONE );
472
473   /**
474    * get backup dir for rpm config files
475    *
476    * */
477   Pathname getBackupPath (void)
478   {
479     return _backuppath;
480   }
481
482   /**
483    * create tar.gz of all changed files in a Package
484    *
485    * @param packageName name of the Package to backup
486    *
487    * @see setBackupPath
488    * */
489   bool backupPackage(const std::string& packageName);
490
491   /**
492    * queries file for name and then calls above backupPackage
493    * function. For convenience.
494    *
495    * @param filename rpm file that is about to be installed
496    * */
497   bool backupPackage(const Pathname& filename);
498
499   /**
500    * set path where package backups are stored
501    *
502    * @see backupPackage
503    * */
504   void setBackupPath(const Pathname& path);
505
506   /**
507    * whether to create package backups during install or
508    * removal
509    *
510    * @param yes true or false
511    * */
512   void createPackageBackups(bool yes)
513   {
514     _packagebackups = yes;
515   }
516
517   /**
518    * determine which files of an installed package have been
519    * modified.
520    *
521    * @param fileList (output) where to store modified files
522    * @param packageName name of package to query
523    *
524    * @return false if package couln't be queried for some
525    * reason
526    * */
527   bool queryChangedFiles(FileList & fileList, const std::string& packageName);
528
529 public:
530
531   /**
532    * Dump debug info.
533    **/
534   virtual std::ostream & dumpOn( std::ostream & str ) const;
535
536 protected:
537   void doRemovePackage( const std::string & name_r, RpmInstFlags flags, callback::SendReport<RpmRemoveReport> & report );
538   void doInstallPackage( const Pathname & filename, RpmInstFlags flags, callback::SendReport<RpmInstallReport> & report );
539   void doRebuildDatabase(callback::SendReport<RebuildDBReport> & report);
540 };
541
542 } // namespace rpm
543 } // namespace target
544 } // namespace zypp
545
546 #endif // ZYPP_TARGET_RPM_RPMDB_H