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