Reimplemented RpmDb::checkPackage using librpm API instead of parsing "rpm --checksig...
[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/Source.h"
28 #include "zypp/KeyRing.h"
29
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          * \throws RpmException
192          *
193          **/
194         void initDatabase( Pathname root_r = Pathname(),
195                            Pathname dbPath_r = Pathname() );
196
197         /**
198          * Block further access to the rpm database and go back to uninitialized
199          * state. On update: Decides what to do with any converted database
200          * (see @ref initDatabase).
201          *
202          * \throws RpmException
203          *
204          **/
205         void closeDatabase();
206
207         /**
208          * Rebuild the rpm database (rpm --rebuilddb).
209          *
210          * \throws RpmException
211          *
212          **/
213         void rebuildDatabase();
214
215         /**
216          * Import ascii armored public key in file pubkey_r.
217          *
218          * \throws RpmException
219          *
220          **/
221         void importPubkey( const Pathname & pubkey_r );
222
223         /**
224          * Return the long ids of all installed public keys.
225          **/
226         std::list<PublicKey> pubkeys() const;
227
228         /**
229          * Return the edition of all installed public keys.
230          **/
231         std::set<Edition> pubkeyEditions() const;
232
233         ///////////////////////////////////////////////////////////////////
234         //
235         // Cached RPM database retrieval via librpm.
236         //
237         ///////////////////////////////////////////////////////////////////
238       private:
239
240         class Packages;
241
242         Packages & _packages;
243
244         std::set<std::string> _filerequires;
245
246       public:
247
248         /**
249          * @return Whether the list of installed packages is valid, or
250          * you'd better reread it. (<B>NOTE:</B> returns valid, if not
251          * initialized).
252          **/
253         bool packagesValid() const;
254
255         /**
256          * If necessary build, and return the list of all installed packages.
257          **/
258         const std::list<Package::Ptr> & getPackages();
259
260         ///////////////////////////////////////////////////////////////////
261         //
262         // Direct RPM database retrieval via librpm.
263         //
264         ///////////////////////////////////////////////////////////////////
265       public:
266
267         /**
268          * return complete file list for installed package name_r (in FileInfo.filename)
269          * if edition_r != Edition::noedition, check for exact edition
270          * if full==true, fill all attributes of FileInfo
271          **/
272         std::list<FileInfo> fileList( const std::string & name_r, const Edition & edition_r ) const;
273
274         /**
275          * Return true if at least one package owns a certain file (name_r empty)
276          * Return true if package name_r owns file file_r (name_r nonempty).
277          **/
278         bool hasFile( const std::string & file_r, const std::string & name_r = "" ) const;
279
280         /**
281          * Return name of package owning file
282          * or empty string if no installed package owns file
283          **/
284         std::string whoOwnsFile( const std::string & file_r ) const;
285
286         /**
287          * Return true if at least one package provides a certain tag.
288          **/
289         bool hasProvides( const std::string & tag_r ) const;
290
291         /**
292          * Return true if at least one package requires a certain tag.
293          **/
294         bool hasRequiredBy( const std::string & tag_r ) const;
295
296         /**
297          * Return true if at least one package conflicts with a certain tag.
298          **/
299         bool hasConflicts( const std::string & tag_r ) const;
300
301         /**
302          * Return true if package is installed.
303          **/
304         bool hasPackage( const std::string & name_r ) const;
305
306         /**
307          * Return true if package is installed in a certain edition.
308          **/
309         bool hasPackage( const std::string & name_r, const Edition & ed_r ) const;
310
311         /**
312          * Get an installed packages data from rpmdb. Package is
313          * identified by name. Data returned via result are NULL,
314          * if packge is not installed (PMError is not set), or RPM database
315          * could not be read (PMError is set).
316          *
317          * \throws RpmException
318          *
319          * FIXME this and following comment
320          *
321          **/
322         void getData( const std::string & name_r,
323                       RpmHeader::constPtr & result_r ) const;
324
325         /**
326          * Get an installed packages data from rpmdb. Package is
327          * identified by name and edition. Data returned via result are NULL,
328          * if packge is not installed (PMError is not set), or RPM database
329          * could not be read (PMError is set).
330          *
331          * \throws RpmException
332          *
333          **/
334         void getData( const std::string & name_r, const Edition & ed_r,
335                       RpmHeader::constPtr & result_r ) const;
336
337
338         /**
339          * Create a package from RpmHeader
340          * return NULL on error
341          **/
342
343         static Package::Ptr makePackageFromHeader( const RpmHeader::constPtr header, std::set<std::string> * filerequires, const Pathname & location, Source_Ref source );
344
345         ///////////////////////////////////////////////////////////////////
346         //
347         ///////////////////////////////////////////////////////////////////
348       public:
349         /**
350          * iterates through zypp keyring and import all non existant keys
351          * into rpm keyring
352          */
353         void importZyppKeyRingTrustedKeys();
354         /**
355          * insert all rpm trusted keys into zypp trusted keyring
356          */
357         void exportTrustedKeysInZyppKeyRing();
358       private:
359         /**
360          * The connection to the rpm process.
361         */
362         ExternalProgram *process;
363
364         typedef std::vector<const char*> RpmArgVec;
365
366         /**
367          * Run rpm with the specified arguments and handle stderr.
368          * @param n_opts The number of arguments
369          * @param options Array of the arguments, @ref n_opts elements
370          * @param stderr_disp How to handle stderr, merged with stdout by default
371          *
372          * \throws RpmException
373          *
374          **/
375         void run_rpm( const RpmArgVec& options,
376                       ExternalProgram::Stderr_Disposition stderr_disp =
377                         ExternalProgram::Stderr_To_Stdout);
378
379
380         /**
381          * Read a line from the general rpm query
382         */
383         bool systemReadLine(std::string &line);
384
385         /**
386          * Return the exit status of the general rpm process,
387          * closing the connection if not already done.
388         */
389         int systemStatus();
390
391         /**
392          * Forcably kill the system process
393         */
394         void systemKill();
395
396         /**
397          * The exit code of the rpm process, or -1 if not yet known.
398         */
399         int exit_code;
400
401         /** /var/adm/backup */
402         Pathname _backuppath;
403
404         /** create package backups? */
405         bool _packagebackups;
406
407         /** whether <_root>/<WARNINGMAILPATH> was already created */
408         bool _warndirexists;
409
410         /**
411          * handle rpm messages like "/etc/testrc saved as /etc/testrc.rpmorig"
412          *
413          * @param line rpm output starting with warning:
414          * @param name name of package, appears in subject line
415          * @param typemsg " saved as " or " created as "
416          * @param difffailmsg what to put into mail if diff failed, must contain two %s for the two files
417          * @param diffgenmsg what to put into mail if diff succeeded, must contain two %s for the two files
418          * */
419         void processConfigFiles(const std::string& line,
420                                 const std::string& name,
421                                 const char* typemsg,
422                                 const char* difffailmsg,
423                                 const char* diffgenmsg);
424
425
426       public:
427
428         typedef std::set<std::string> FileList;
429
430         /**
431          * Bits representing rpm installation options, useable as or
432          * combination
433          *
434          * @see installPackage(), removePackage()
435          * */
436         enum RpmInstFlag
437         {
438           RPMINST_NONE       = 0x0000,
439           RPMINST_NODOCS     = 0x0001,
440           RPMINST_NOSCRIPTS  = 0x0002,
441           RPMINST_FORCE      = 0x0004,
442           RPMINST_NODEPS     = 0x0008,
443           RPMINST_IGNORESIZE = 0x0010,
444           RPMINST_JUSTDB     = 0x0020,
445           RPMINST_NODIGEST   = 0x0040,
446           RPMINST_NOSIGNATURE= 0x0080,
447           RPMINST_NOUPGRADE  = 0x0100,
448           RPMINST_TEST   = 0x0200
449         };
450
451         /**
452          * checkPackage result
453          * @see checkPackage
454          * */
455         enum checkPackageResult
456         {
457           CHK_OK            = 0, /*!< Signature is OK. */
458           CHK_NOTFOUND      = 1, /*!< Signature is unknown type. */
459           CHK_FAIL          = 2, /*!< Signature does not verify. */
460           CHK_NOTTRUSTED    = 3, /*!< Signature is OK, but key is not trusted. */
461           CHK_NOKEY         = 4, /*!< Public key is unavailable. */
462           CHK_ERROR         = 5  /*!< File does not exist or can't be opened. */
463         };
464
465         /**
466          * Check signature of rpm file on disk.
467          *
468          * @param filename which file to check
469          *
470          * @return checkPackageResult
471         */
472         checkPackageResult checkPackage( const Pathname & path_r );
473
474         /** install rpm package
475          *
476          * @param filename file to install
477          * @param flags which rpm options to use
478          *
479          * @return success
480          *
481          * \throws RpmException
482          *
483          * */
484         void installPackage (const Pathname& filename, unsigned flags = 0 );
485
486         /** remove rpm package
487          *
488          * @param name_r Name of the rpm package to remove.
489          * @param iflags which rpm options to use
490          *
491          * @return success
492          *
493          * \throws RpmException
494          *
495          * */
496         void removePackage(const std::string & name_r, unsigned flags = 0);
497         void removePackage(Package::constPtr package, unsigned flags = 0);
498
499         /**
500          * get backup dir for rpm config files
501          *
502          * */
503         Pathname getBackupPath (void)
504         {
505           return _backuppath;
506         }
507
508         /**
509          * create tar.gz of all changed files in a Package
510          *
511          * @param packageName name of the Package to backup
512          *
513          * @see setBackupPath
514          * */
515         bool backupPackage(const std::string& packageName);
516
517         /**
518          * queries file for name and then calls above backupPackage
519          * function. For convenience.
520          *
521          * @param filename rpm file that is about to be installed
522          * */
523         bool backupPackage(const Pathname& filename);
524
525         /**
526          * set path where package backups are stored
527          *
528          * @see backupPackage
529          * */
530         void setBackupPath(const Pathname& path);
531
532         /**
533          * whether to create package backups during install or
534          * removal
535          *
536          * @param yes true or false
537          * */
538         void createPackageBackups(bool yes)
539         {
540           _packagebackups = yes;
541         }
542
543         /**
544          * determine which files of an installed package have been
545          * modified.
546          *
547          * @param fileList (output) where to store modified files
548          * @param packageName name of package to query
549          *
550          * @return false if package couln't be queried for some
551          * reason
552          * */
553         bool queryChangedFiles(FileList & fileList, const std::string& packageName);
554
555       public:
556
557         /**
558          * Dump debug info.
559          **/
560         virtual std::ostream & dumpOn( std::ostream & str ) const;
561
562       protected:
563         void doRemovePackage( const std::string & name_r, unsigned flags, callback::SendReport<RpmRemoveReport> & report );
564         void doInstallPackage( const Pathname & filename, unsigned flags, callback::SendReport<RpmInstallReport> & report );
565         const std::list<Package::Ptr> & doGetPackages(callback::SendReport<ScanDBReport> & report);
566         void doRebuildDatabase(callback::SendReport<RebuildDBReport> & report);
567
568
569       };
570
571     } // namespace rpm
572   } // namespace target
573 } // namespace zypp
574
575 #endif // ZYPP_TARGET_RPM_RPMDB_H