1 /*
2  * Copyright (C) 2012-2014 Red Hat, Inc.
3  *
4  * Licensed under the GNU Lesser General Public License Version 2.1
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * SECTION:dnf-package
23  * @short_description: Package
24  * @include: libdnf.h
25  * @stability: Unstable
26  *
27  * An object representing a package in the system.
28  *
29  * See also: #DnfContext
30  */
31 
32 #include "libdnf/utils/utils.hpp"
33 
34 #include <algorithm>
35 #include <ctime>
36 #include <stdlib.h>
37 #include <solv/evr.h>
38 #include <solv/pool.h>
39 #include <solv/repo.h>
40 #include <solv/queue.h>
41 
42 #include "dnf-advisory-private.hpp"
43 #include "dnf-packagedelta-private.hpp"
44 #include "dnf-sack-private.hpp"
45 #include "hy-iutil-private.hpp"
46 #include "hy-package-private.hpp"
47 #include "hy-repo-private.hpp"
48 #include "repo/solvable/DependencyContainer.hpp"
49 #include "sack/advisorymodule.hpp"
50 
51 #define BLOCK_SIZE 31
52 
53 typedef struct
54 {
55     gboolean         loaded;
56     Id               id;
57     DnfSack         *sack;
58 } DnfPackagePrivate;
59 
G_DEFINE_TYPE_WITH_PRIVATE(DnfPackage,dnf_package,G_TYPE_OBJECT)60 G_DEFINE_TYPE_WITH_PRIVATE(DnfPackage, dnf_package, G_TYPE_OBJECT)
61 #define GET_PRIVATE(o) (static_cast<DnfPackagePrivate *>(dnf_package_get_instance_private (o)))
62 
63 /**
64  * dnf_package_finalize:
65  **/
66 static void
67 dnf_package_finalize(GObject *object)
68 {
69     G_OBJECT_CLASS(dnf_package_parent_class)->finalize(object);
70 }
71 
72 /**
73  * dnf_package_init:
74  **/
75 static void
dnf_package_init(DnfPackage * package)76 dnf_package_init(DnfPackage *package)
77 {
78 }
79 
80 /**
81  * dnf_package_class_init:
82  **/
83 static void
dnf_package_class_init(DnfPackageClass * klass)84 dnf_package_class_init(DnfPackageClass *klass)
85 {
86     GObjectClass *object_class = G_OBJECT_CLASS(klass);
87     object_class->finalize = dnf_package_finalize;
88 }
89 
90 
91 /**
92  * dnf_package_new:
93  *
94  * Creates a new #DnfPackage.
95  *
96  * Returns:(transfer full): a #DnfPackage
97  *
98  * Since: 0.7.0
99  **/
100 DnfPackage *
dnf_package_new(DnfSack * sack,Id id)101 dnf_package_new(DnfSack *sack, Id id)
102 {
103     auto pkg = DNF_PACKAGE(g_object_new(DNF_TYPE_PACKAGE, NULL));
104     auto priv = GET_PRIVATE(pkg);
105     priv->sack = sack;
106     priv->id = id;
107     return pkg;
108 }
109 
110 
111 /* internal */
112 static Solvable *
get_solvable(DnfPackage * pkg)113 get_solvable(DnfPackage *pkg)
114 {
115     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
116     return pool_id2solvable(dnf_package_get_pool(pkg), priv->id);
117 }
118 
119 /**
120  * dnf_package_get_pool: (skip)
121  * @pkg: a #DnfPackage instance.
122  *
123  * Gets the pool used for storage.
124  *
125  * Returns: (transfer none): a %Pool
126  *
127  * Since: 0.7.0
128  */
129 Pool *
dnf_package_get_pool(DnfPackage * pkg)130 dnf_package_get_pool(DnfPackage *pkg)
131 {
132     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
133     return dnf_sack_get_pool(priv->sack);
134 }
135 
136 static guint64
lookup_num(DnfPackage * pkg,unsigned type)137 lookup_num(DnfPackage *pkg, unsigned type)
138 {
139     Solvable *s = get_solvable(pkg);
140     repo_internalize_trigger(s->repo);
141     return solvable_lookup_num(s, type, 0);
142 }
143 
144 static DnfReldepList *
reldeps_for(DnfPackage * pkg,Id type)145 reldeps_for(DnfPackage *pkg, Id type)
146 {
147     Solvable *s = get_solvable(pkg);
148     DnfReldepList *reldeplist;
149     Queue q;
150     Id marker = -1;
151     Id solv_type = type;
152 
153     if (type == SOLVABLE_REQUIRES)
154         marker = -1;
155 
156     if (type == SOLVABLE_PREREQMARKER) {
157         solv_type = SOLVABLE_REQUIRES;
158         marker = 1;
159     }
160     queue_init(&q);
161     solvable_lookup_deparray(s, solv_type, &q, marker);
162 
163     reldeplist = new libdnf::DependencyContainer(dnf_package_get_sack(pkg), std::move(q));
164 
165     return reldeplist;
166 }
167 
168 /**
169  * dnf_package_get_id: (skip):
170  * @pkg: a #DnfPackage instance.
171  *
172  * Gets the internal ID used to identify the package in the pool.
173  *
174  * Returns: an integer, or 0 for unknown
175  *
176  * Since: 0.7.0
177  */
178 Id
dnf_package_get_id(DnfPackage * pkg)179 dnf_package_get_id(DnfPackage *pkg)
180 {
181     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
182     return priv->id;
183 }
184 
185 /**
186  * dnf_package_get_sack:
187  * @pkg: a #DnfPackage instance.
188  *
189  * Gets the package sack for the package.
190  *
191  * Returns: a #DnfSack, or %NULL
192  *
193  * Since: 0.7.0
194  */
195 DnfSack *
dnf_package_get_sack(DnfPackage * pkg)196 dnf_package_get_sack(DnfPackage *pkg)
197 {
198     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
199     return priv->sack;
200 }
201 
202 /**
203  * dnf_package_get_identical:
204  * @pkg1: a #DnfPackage instance.
205  * @pkg2: another #DnfPackage instance.
206  *
207  * Tests two packages for equality.
208  *
209  * Returns: %TRUE if the packages are the same
210  *
211  * Since: 0.7.0
212  */
213 gboolean
dnf_package_get_identical(DnfPackage * pkg1,DnfPackage * pkg2)214 dnf_package_get_identical(DnfPackage *pkg1, DnfPackage *pkg2)
215 {
216     DnfPackagePrivate *priv1 = GET_PRIVATE(pkg1);
217     DnfPackagePrivate *priv2 = GET_PRIVATE(pkg2);
218     return priv1->id == priv2->id;
219 }
220 
221 /**
222  * dnf_package_installed:
223  * @pkg: a #DnfPackage instance.
224  *
225  * Tests if the package is installed.
226  *
227  * Returns: %TRUE if installed
228  *
229  * Since: 0.7.0
230  */
231 gboolean
dnf_package_installed(DnfPackage * pkg)232 dnf_package_installed(DnfPackage *pkg)
233 {
234     Solvable *s = get_solvable(pkg);
235     return (dnf_package_get_pool(pkg)->installed == s->repo);
236 }
237 
238 /**
239  * dnf_package_cmp:
240  * @pkg1: a #DnfPackage instance.
241  * @pkg2: another #DnfPackage instance.
242  *
243  * Compares two packages.
244  *
245  * Returns: %TRUE for success
246  *
247  * Since: 0.7.0
248  */
249 int
dnf_package_cmp(DnfPackage * pkg1,DnfPackage * pkg2)250 dnf_package_cmp(DnfPackage *pkg1, DnfPackage *pkg2)
251 {
252     Pool *pool1 = dnf_package_get_pool(pkg1);
253     Pool *pool2 = dnf_package_get_pool(pkg2);
254     Solvable *s1 = pool_id2solvable(pool1, dnf_package_get_id(pkg1));
255     Solvable *s2 = pool_id2solvable(pool2, dnf_package_get_id(pkg2));
256     const char *str1 = pool_id2str(pool1, s1->name);
257     const char *str2 = pool_id2str(pool2, s2->name);
258     int ret = strcmp(str1, str2);
259     if (ret)
260         return ret;
261 
262     ret = dnf_package_evr_cmp(pkg1, pkg2);
263     if (ret)
264         return ret;
265 
266     str1 = pool_id2str(pool1, s1->arch);
267     str2 = pool_id2str(pool2, s2->arch);
268     return strcmp(str1, str2);
269 }
270 
271 /**
272  * dnf_package_evr_cmp:
273  * @pkg1: a #DnfPackage instance.
274  * @pkg2: another #DnfPackage instance.
275  *
276  * Compares two packages, only using the EVR values.
277  *
278  * Returns: %TRUE for success
279  *
280  * Since: 0.7.0
281  */
282 int
dnf_package_evr_cmp(DnfPackage * pkg1,DnfPackage * pkg2)283 dnf_package_evr_cmp(DnfPackage *pkg1, DnfPackage *pkg2)
284 {
285     Pool *pool1 = dnf_package_get_pool(pkg1);
286     Pool *pool2 = dnf_package_get_pool(pkg2);
287     Solvable *s1 = get_solvable(pkg1);
288     Solvable *s2 = get_solvable(pkg2);
289     const char *str1 = pool_id2str(pool1, s1->evr);
290     const char *str2 = pool_id2str(pool2, s2->evr);
291 
292     return pool_evrcmp_str(dnf_package_get_pool(pkg1), str1, str2, EVRCMP_COMPARE);
293 }
294 
295 /**
296  * dnf_package_get_location:
297  * @pkg: a #DnfPackage instance.
298  *
299  * Gets the location (XXX??) for the package. Note that the returned string has
300  * an undefined lifetime and may become invalid at a later time. You should copy
301  * the string if storing it into a long-lived data structure.
302  *
303  * Returns: (transfer none): string
304  *
305  * Since: 0.7.0
306  */
307 const char *
dnf_package_get_location(DnfPackage * pkg)308 dnf_package_get_location(DnfPackage *pkg)
309 {
310     Solvable *s = get_solvable(pkg);
311     repo_internalize_trigger(s->repo);
312     return solvable_get_location(s, NULL);
313 }
314 
315 /**
316  * dnf_package_get_baseurl:
317  * @pkg: a #DnfPackage instance.
318  *
319  * Gets the baseurl for the package.
320  *
321  * Returns: a string, or %NULL
322  *
323  * Since: 0.7.0
324  */
325 const char *
dnf_package_get_baseurl(DnfPackage * pkg)326 dnf_package_get_baseurl(DnfPackage *pkg)
327 {
328     Solvable *s = get_solvable(pkg);
329     return solvable_lookup_str(s, SOLVABLE_MEDIABASE);
330 }
331 
332 /**
333  * dnf_package_get_nevra:
334  * @pkg: a #DnfPackage instance.
335  *
336  * Gets the package NEVRA. Note that the returned string has an undefined
337  * lifetime and may become invalid at a later time. You should copy the string
338  * if storing it into a long-lived data structure.
339  *
340  * Returns: (transfer none): a string, or %NULL
341  *
342  * Since: 0.7.0
343  */
344 const char *
dnf_package_get_nevra(DnfPackage * pkg)345 dnf_package_get_nevra(DnfPackage *pkg)
346 {
347     Solvable *s = get_solvable(pkg);
348     return pool_solvable2str(dnf_package_get_pool(pkg), s);
349 }
350 
351 /**
352  * dnf_package_get_sourcerpm:
353  * @pkg: a #DnfPackage instance.
354  *
355  * Gets the source RPM for the package.
356  *
357  * Returns: (transfer none): a string, or %NULL
358  *
359  * Since: 0.7.0
360  */
361 const char *
dnf_package_get_sourcerpm(DnfPackage * pkg)362 dnf_package_get_sourcerpm(DnfPackage *pkg)
363 {
364     Solvable *s = get_solvable(pkg);
365     repo_internalize_trigger(s->repo);
366     return solvable_lookup_sourcepkg(s);
367 }
368 
369 /**
370  * dnf_package_get_version:
371  * @pkg: a #DnfPackage instance.
372  *
373  * Gets the version for the package.
374  *
375  * Returns: (transfer none): a string, or %NULL
376  *
377  * Since: 0.7.0
378  */
379 const char *
dnf_package_get_version(DnfPackage * pkg)380 dnf_package_get_version(DnfPackage *pkg)
381 {
382     char *e, *v, *r;
383     pool_split_evr(dnf_package_get_pool(pkg), dnf_package_get_evr(pkg), &e, &v, &r);
384     return v;
385 }
386 
387 /**
388  * dnf_package_get_release:
389  * @pkg: a #DnfPackage instance.
390  *
391  * Gets the release for the package.
392  *
393  * Returns: (transfer none): a string, or %NULL
394  *
395  * Since: 0.7.0
396  */
397 const char *
dnf_package_get_release(DnfPackage * pkg)398 dnf_package_get_release(DnfPackage *pkg)
399 {
400     char *e, *v, *r;
401     pool_split_evr(dnf_package_get_pool(pkg), dnf_package_get_evr(pkg), &e, &v, &r);
402     return r;
403 }
404 
405 /**
406  * dnf_package_get_name:
407  * @pkg: a #DnfPackage instance.
408  *
409  * Gets the name for the package.
410  *
411  * Returns: a string, or %NULL
412  *
413  * Since: 0.7.0
414  */
415 const char *
dnf_package_get_name(DnfPackage * pkg)416 dnf_package_get_name(DnfPackage *pkg)
417 {
418     Pool *pool = dnf_package_get_pool(pkg);
419     return pool_id2str(pool, get_solvable(pkg)->name);
420 }
421 
422 /**
423  * dnf_package_get_vendor:
424  * @pkg: a #DnfPackage instance.
425  *
426  * Gets the name for the package.
427  *
428  * Returns: a string, or %NULL
429  *
430  * Since: 0.54.4
431  */
432 const char *
dnf_package_get_vendor(DnfPackage * pkg)433 dnf_package_get_vendor(DnfPackage *pkg)
434 {
435     Pool *pool = dnf_package_get_pool(pkg);
436     return pool_id2str(pool, get_solvable(pkg)->vendor);
437 }
438 
439 /**
440  * dnf_package_get_packager:
441  * @pkg: a #DnfPackage instance.
442  *
443  * Gets the XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX for the package.
444  *
445  * Returns: a string, or %NULL
446  *
447  * Since: 0.7.0
448  */
449 const char *
dnf_package_get_packager(DnfPackage * pkg)450 dnf_package_get_packager(DnfPackage *pkg)
451 {
452     return solvable_lookup_str(get_solvable(pkg), SOLVABLE_PACKAGER);
453 }
454 
455 /**
456  * dnf_package_get_arch:
457  * @pkg: a #DnfPackage instance.
458  *
459  * Gets the architecture for the package.
460  *
461  * Returns: a string, or %NULL
462  *
463  * Since: 0.7.0
464  */
465 const char *
dnf_package_get_arch(DnfPackage * pkg)466 dnf_package_get_arch(DnfPackage *pkg)
467 {
468     Pool *pool = dnf_package_get_pool(pkg);
469     return pool_id2str(pool, get_solvable(pkg)->arch);
470 }
471 
472 /**
473  * dnf_package_get_chksum:
474  * @pkg: a #DnfPackage instance.
475  *
476  * Gets the checksum for the package.
477  *
478  * Returns: raw checksum bytes
479  *
480  * Since: 0.7.0
481  */
482 const unsigned char *
dnf_package_get_chksum(DnfPackage * pkg,int * type)483 dnf_package_get_chksum(DnfPackage *pkg, int *type)
484 {
485     Solvable *s = get_solvable(pkg);
486     const unsigned char* ret;
487 
488     repo_internalize_trigger(s->repo);
489     ret = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, type);
490     if (ret)
491         *type = checksumt_l2h(*type);
492     return ret;
493 }
494 
495 /**
496  * dnf_package_get_hdr_chksum:
497  * @pkg: a #DnfPackage instance.
498  *
499  * Gets the SHA1 checksum of the packages header.
500  * This is only set for packages in the rpmdb.
501  *
502  * Returns: raw checksum bytes
503  *
504  * Since: 0.7.0
505  */
506 const unsigned char *
dnf_package_get_hdr_chksum(DnfPackage * pkg,int * type)507 dnf_package_get_hdr_chksum(DnfPackage *pkg, int *type)
508 {
509     Solvable *s = get_solvable(pkg);
510     const unsigned char *ret;
511 
512     repo_internalize_trigger(s->repo);
513     ret = solvable_lookup_bin_checksum(s, SOLVABLE_HDRID, type);
514     if (ret)
515         *type = checksumt_l2h(*type);
516     return ret;
517 }
518 
519 /**
520  * dnf_package_get_description:
521  * @pkg: a #DnfPackage instance.
522  *
523  * Gets the description for the package.
524  *
525  * Returns: a string, or %NULL
526  *
527  * Since: 0.7.0
528  */
529 const char *
dnf_package_get_description(DnfPackage * pkg)530 dnf_package_get_description(DnfPackage *pkg)
531 {
532     return solvable_lookup_str(get_solvable(pkg), SOLVABLE_DESCRIPTION);
533 }
534 
535 /**
536  * dnf_package_get_evr:
537  * @pkg: a #DnfPackage instance.
538  *
539  * Gets the EVR for the package.
540  *
541  * Returns: a string
542  *
543  * Since: 0.7.0
544  */
545 const char *
dnf_package_get_evr(DnfPackage * pkg)546 dnf_package_get_evr(DnfPackage *pkg)
547 {
548     Pool *pool = dnf_package_get_pool(pkg);
549     return pool_id2str(pool, get_solvable(pkg)->evr);
550 }
551 
552 /**
553  * dnf_package_get_group:
554  * @pkg: a #DnfPackage instance.
555  *
556  * Gets the group for the package.
557  *
558  * Returns: a string, or %NULL
559  *
560  * Since: 0.7.0
561  */
562 const char *
dnf_package_get_group(DnfPackage * pkg)563 dnf_package_get_group(DnfPackage *pkg)
564 {
565   return solvable_lookup_str(get_solvable(pkg), SOLVABLE_GROUP);
566 }
567 
568 /**
569  * dnf_package_get_license:
570  * @pkg: a #DnfPackage instance.
571  *
572  * Gets the license for the package.
573  *
574  * Returns: a string, or %NULL
575  *
576  * Since: 0.7.0
577  */
578 const char *
dnf_package_get_license(DnfPackage * pkg)579 dnf_package_get_license(DnfPackage *pkg)
580 {
581     return solvable_lookup_str(get_solvable(pkg), SOLVABLE_LICENSE);
582 }
583 
584 /**
585  * dnf_package_get_reponame:
586  * @pkg: a #DnfPackage instance.
587  *
588  * Gets the reponame for the package.
589  *
590  * Returns: a string, or %NULL
591  *
592  * Since: 0.7.0
593  */
594 const char *
dnf_package_get_reponame(DnfPackage * pkg)595 dnf_package_get_reponame(DnfPackage *pkg)
596 {
597     Solvable *s = get_solvable(pkg);
598     return s->repo->name;
599 }
600 
601 /**
602  * dnf_package_get_summary:
603  * @pkg: a #DnfPackage instance.
604  *
605  * Gets the summary for the package.
606  *
607  * Returns: a string, or %NULL
608  *
609  * Since: 0.7.0
610  */
611 const char *
dnf_package_get_summary(DnfPackage * pkg)612 dnf_package_get_summary(DnfPackage *pkg)
613 {
614     Solvable *s = get_solvable(pkg);
615     return solvable_lookup_str(s, SOLVABLE_SUMMARY);
616 }
617 
618 /**
619  * dnf_package_get_url:
620  * @pkg: a #DnfPackage instance.
621  *
622  * Gets the url for the package.
623  *
624  * Returns: a string, or %NULL
625  *
626  * Since: 0.7.0
627  */
628 const char *
dnf_package_get_url(DnfPackage * pkg)629 dnf_package_get_url(DnfPackage *pkg)
630 {
631     return solvable_lookup_str(get_solvable(pkg), SOLVABLE_URL);
632 }
633 
634 /**
635  * dnf_package_get_downloadsize:
636  * @pkg: a #DnfPackage instance.
637  *
638  * Gets the download size for the package.
639  *
640  * Returns: %TRUE for success
641  *
642  * Since: 0.7.0
643  */
644 guint64
dnf_package_get_downloadsize(DnfPackage * pkg)645 dnf_package_get_downloadsize(DnfPackage *pkg)
646 {
647     return lookup_num(pkg, SOLVABLE_DOWNLOADSIZE);
648 }
649 
650 /**
651  * dnf_package_get_epoch:
652  * @pkg: a #DnfPackage instance.
653  *
654  * Gets the epoch for the package.
655  *
656  * Returns: %TRUE for success
657  *
658  * Since: 0.7.0
659  */
660 guint64
dnf_package_get_epoch(DnfPackage * pkg)661 dnf_package_get_epoch(DnfPackage *pkg)
662 {
663     return pool_get_epoch(dnf_package_get_pool(pkg), dnf_package_get_evr(pkg));
664 }
665 
666 /**
667  * dnf_package_get_hdr_end:
668  * @pkg: a #DnfPackage instance.
669  *
670  * Gets the header end index for the package.
671  *
672  * Returns: an index, or 0 for not known
673  *
674  * Since: 0.7.0
675  */
676 guint64
dnf_package_get_hdr_end(DnfPackage * pkg)677 dnf_package_get_hdr_end(DnfPackage *pkg)
678 {
679     return lookup_num(pkg, SOLVABLE_HEADEREND);
680 }
681 
682 /**
683  * dnf_package_get_installsize:
684  * @pkg: a #DnfPackage instance.
685  *
686  * Gets the installed size for the package.
687  *
688  * Returns: size in bytes
689  *
690  * Since: 0.7.0
691  */
692 guint64
dnf_package_get_installsize(DnfPackage * pkg)693 dnf_package_get_installsize(DnfPackage *pkg)
694 {
695     return lookup_num(pkg, SOLVABLE_INSTALLSIZE);
696 }
697 
698 /**
699  * dnf_package_get_buildtime:
700  * @pkg: a #DnfPackage instance.
701  *
702  * Gets the build time for the package.
703  *
704  * Returns: UNIX time
705  *
706  * Since: 0.7.0
707  */
708 guint64
dnf_package_get_buildtime(DnfPackage * pkg)709 dnf_package_get_buildtime(DnfPackage *pkg)
710 {
711     return lookup_num(pkg, SOLVABLE_BUILDTIME);
712 }
713 
714 /**
715  * dnf_package_get_installtime:
716  * @pkg: a #DnfPackage instance.
717  *
718  * Gets the install time for the package.
719  *
720  * Returns: UNIX time
721  *
722  * Since: 0.7.0
723  */
724 guint64
dnf_package_get_installtime(DnfPackage * pkg)725 dnf_package_get_installtime(DnfPackage *pkg)
726 {
727     return lookup_num(pkg, SOLVABLE_INSTALLTIME);
728 }
729 
730 /**
731  * dnf_package_get_medianr:
732  * @pkg: a #DnfPackage instance.
733  *
734  * Gets the media number for the package.
735  *
736  * Returns: integer value
737  *
738  * Since: 0.7.0
739  */
740 guint64
dnf_package_get_medianr(DnfPackage * pkg)741 dnf_package_get_medianr(DnfPackage *pkg)
742 {
743     return lookup_num(pkg, SOLVABLE_MEDIANR);
744 }
745 
746 /**
747  * dnf_package_get_rpmdbid:
748  * @pkg: a #DnfPackage instance.
749  *
750  * Gets the RPMDB ID for the package.
751  *
752  * Returns: an ID, or 0 for not known
753  *
754  * Since: 0.7.0
755  */
756 guint64
dnf_package_get_rpmdbid(DnfPackage * pkg)757 dnf_package_get_rpmdbid(DnfPackage *pkg)
758 {
759     guint64 ret = lookup_num(pkg, RPM_RPMDBID);
760     return ret;
761 }
762 
763 /**
764  * dnf_package_get_size:
765  * @pkg: a #DnfPackage instance.
766  *
767  * Gets the size for the package.
768  *
769  * Returns: size in bytes
770  *
771  * Since: 0.7.0
772  */
773 guint64
dnf_package_get_size(DnfPackage * pkg)774 dnf_package_get_size(DnfPackage *pkg)
775 {
776     unsigned type = dnf_package_installed(pkg) ? SOLVABLE_INSTALLSIZE :
777                                                  SOLVABLE_DOWNLOADSIZE;
778     return lookup_num(pkg, type);
779 }
780 
781 /**
782  * dnf_package_get_conflicts:
783  * @pkg: a #DnfPackage instance.
784  *
785  * Gets the conflicts for the package.
786  *
787  * Returns: A #DnfReldepList
788  *
789  * Since: 0.7.0
790  */
791 DnfReldepList *
dnf_package_get_conflicts(DnfPackage * pkg)792 dnf_package_get_conflicts(DnfPackage *pkg)
793 {
794     return reldeps_for(pkg, SOLVABLE_CONFLICTS);
795 }
796 
797 /**
798  * dnf_package_get_enhances:
799  * @pkg: a #DnfPackage instance.
800  *
801  * Gets the enhances for the package.
802  *
803  * Returns: A #DnfReldepList
804  *
805  * Since: 0.7.0
806  */
807 DnfReldepList *
dnf_package_get_enhances(DnfPackage * pkg)808 dnf_package_get_enhances(DnfPackage *pkg)
809 {
810     return reldeps_for(pkg, SOLVABLE_ENHANCES);
811 }
812 
813 /**
814  * dnf_package_get_obsoletes:
815  * @pkg: a #DnfPackage instance.
816  *
817  * Gets the obsoletes for the package.
818  *
819  * Returns: A #DnfReldepList
820  *
821  * Since: 0.7.0
822  */
823 DnfReldepList *
dnf_package_get_obsoletes(DnfPackage * pkg)824 dnf_package_get_obsoletes(DnfPackage *pkg)
825 {
826     return reldeps_for(pkg, SOLVABLE_OBSOLETES);
827 }
828 
829 /**
830  * dnf_package_get_provides:
831  * @pkg: a #DnfPackage instance.
832  *
833  * Gets the provides for the package.
834  *
835  * Returns: A #DnfReldepList
836  *
837  * Since: 0.7.0
838  */
839 DnfReldepList *
dnf_package_get_provides(DnfPackage * pkg)840 dnf_package_get_provides(DnfPackage *pkg)
841 {
842     return reldeps_for(pkg, SOLVABLE_PROVIDES);
843 }
844 
845 /**
846  * dnf_package_get_recommends:
847  * @pkg: a #DnfPackage instance.
848  *
849  * Gets the recommends for the package.
850  *
851  * Returns: A #DnfReldepList
852  *
853  * Since: 0.7.0
854  */
855 DnfReldepList *
dnf_package_get_recommends(DnfPackage * pkg)856 dnf_package_get_recommends(DnfPackage *pkg)
857 {
858     return reldeps_for(pkg, SOLVABLE_RECOMMENDS);
859 }
860 
861 /**
862  * dnf_package_get_requires:
863  * @pkg: a #DnfPackage instance.
864  *
865  * Gets the requires for the package.
866  *
867  * Returns: A #DnfReldepList
868  *
869  * Since: 0.7.0
870  */
871 DnfReldepList *
dnf_package_get_requires(DnfPackage * pkg)872 dnf_package_get_requires(DnfPackage *pkg)
873 {
874 
875     DnfReldepList * l = reldeps_for(pkg, SOLVABLE_REQUIRES);
876     DnfReldepList * prereq_l = reldeps_for(pkg, SOLVABLE_PREREQMARKER);
877     l->extend(prereq_l);
878     delete prereq_l;
879     return l;
880 }
881 
882 /**
883  * dnf_package_get_requires_pre:
884  * @pkg: a #DnfPackage instance.
885  *
886  * If the package is not installed gets the Requires(pre) and Requires(post).
887  * If the package is installed it gets Requires(pre), Requires(post),
888  * Requies(preun) and Requires(postun).
889  *
890  * Returns: A #DnfReldepList
891  *
892  * Since: 0.7.0
893  */
894 DnfReldepList *
dnf_package_get_requires_pre(DnfPackage * pkg)895 dnf_package_get_requires_pre (DnfPackage *pkg)
896 {
897     return reldeps_for(pkg, SOLVABLE_PREREQMARKER);
898 }
899 
900 /**
901  * dnf_package_get_suggests:
902  * @pkg: a #DnfPackage instance.
903  *
904  * Gets the suggests for the package.
905  *
906  * Returns: A #DnfReldepList
907  *
908  * Since: 0.7.0
909  */
910 DnfReldepList *
dnf_package_get_suggests(DnfPackage * pkg)911 dnf_package_get_suggests(DnfPackage *pkg)
912 {
913     return reldeps_for(pkg, SOLVABLE_SUGGESTS);
914 }
915 
916 /**
917  * dnf_package_get_supplements:
918  * @pkg: a #DnfPackage instance.
919  *
920  * Gets the supplements for the package.
921  *
922  * Returns: A #DnfReldepList
923  *
924  * Since: 0.7.0
925  */
926 DnfReldepList *
dnf_package_get_supplements(DnfPackage * pkg)927 dnf_package_get_supplements(DnfPackage *pkg)
928 {
929     return reldeps_for(pkg, SOLVABLE_SUPPLEMENTS);
930 }
931 
932 /**
933  * dnf_package_get_prereq_ignoreinst
934  * @pkg: a #DnfPackage instance.
935  *
936  * Returns safe to remove Requires(pre) and Requires(post) dependencies
937  * of the package. Safe to remove means that the dependency is not needed by
938  * Requires(preun) nor by Requires(postun).
939  * The package must be installed otherwise empty list is returned.
940  *
941  * Returns: A #DnfReldepList
942  *
943  * Since: 0.45.1
944  */
945 DnfReldepList *
dnf_package_get_prereq_ignoreinst(DnfPackage * pkg)946 dnf_package_get_prereq_ignoreinst(DnfPackage *pkg)
947 {
948     return reldeps_for(pkg, SOLVABLE_PREREQ_IGNOREINST);
949 }
950 
951 /**
952  * dnf_package_get_regular_requires
953  * @pkg: a #DnfPackage instance.
954  *
955  * Get the requires for the package without Requires(pre), Requires(post)
956  * Requires(preun) and Requires(postun).
957  *
958  * Returns: A #DnfReldepList
959  *
960  * Since: 0.45.1
961  */
962 DnfReldepList *
dnf_package_get_regular_requires(DnfPackage * pkg)963 dnf_package_get_regular_requires(DnfPackage *pkg)
964 {
965     return reldeps_for(pkg, SOLVABLE_REQUIRES);
966 }
967 
968 /**
969  * dnf_package_get_files:
970  * @pkg: a #DnfPackage instance.
971  *
972  * Gets the files contained in the package.
973  *
974  * Returns: (transfer full): the file list
975  *
976  * Since: 0.7.0
977  */
978 gchar **
dnf_package_get_files(DnfPackage * pkg)979 dnf_package_get_files(DnfPackage *pkg)
980 {
981     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
982     Pool *pool = dnf_package_get_pool(pkg);
983     Solvable *s = get_solvable(pkg);
984     Dataiterator di;
985     GPtrArray *ret = g_ptr_array_new();
986 
987     repo_internalize_trigger(s->repo);
988     dataiterator_init(&di, pool, s->repo, priv->id, SOLVABLE_FILELIST, NULL,
989                       SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
990     while (dataiterator_step(&di)) {
991         g_ptr_array_add(ret, g_strdup(di.kv.str));
992     }
993     dataiterator_free(&di);
994     g_ptr_array_add(ret, NULL);
995     return (gchar**)g_ptr_array_free (ret, FALSE);
996 }
997 
998 /**
999  * dnf_package_get_changelogs:
1000  * @pkg: a #DnfPackage instance.
1001  *
1002  * Gets the list of changelogs for the package.
1003  *
1004  * Returns: (transfer container) (element-type Changelog): a list
1005  *
1006  * Since: 0.19.1
1007  */
1008 std::vector<libdnf::Changelog>
dnf_package_get_changelogs(DnfPackage * pkg)1009 dnf_package_get_changelogs(DnfPackage *pkg)
1010 {
1011     DnfPackagePrivate *priv = GET_PRIVATE(pkg);
1012     Pool *pool = dnf_package_get_pool(pkg);
1013     Solvable *s = get_solvable(pkg);
1014     Dataiterator di;
1015     std::vector<libdnf::Changelog> changelogslist;
1016 
1017     dataiterator_init(&di, pool, s->repo, priv->id, SOLVABLE_CHANGELOG_AUTHOR, NULL, 0);
1018     dataiterator_prepend_keyname(&di, SOLVABLE_CHANGELOG);
1019     while (dataiterator_step(&di)) {
1020         dataiterator_setpos_parent(&di);
1021         std::string author(pool_lookup_str(pool, SOLVID_POS, SOLVABLE_CHANGELOG_AUTHOR));
1022         std::string text(pool_lookup_str(pool, SOLVID_POS, SOLVABLE_CHANGELOG_TEXT));
1023         changelogslist.emplace_back(
1024             static_cast<time_t>(pool_lookup_num(pool, SOLVID_POS, SOLVABLE_CHANGELOG_TIME, 0)),
1025             std::move(author), std::move(text));
1026     }
1027     dataiterator_free(&di);
1028     std::reverse(changelogslist.begin(), changelogslist.end());
1029     return changelogslist;
1030 }
1031 
1032 /**
1033  * dnf_package_get_advisories:
1034  * @pkg: a #DnfPackage instance.
1035  *
1036  * Gets the list of advisories for the package.
1037  *
1038  * Returns: (transfer container) (element-type DnfAdvisory): a list
1039  *
1040  * Since: 0.7.0
1041  */
1042 GPtrArray *
dnf_package_get_advisories(DnfPackage * pkg,int cmp_type)1043 dnf_package_get_advisories(DnfPackage *pkg, int cmp_type)
1044 {
1045     Dataiterator di;
1046     Id evr;
1047     int cmp;
1048     Pool *pool = dnf_package_get_pool(pkg);
1049     DnfSack *sack = dnf_package_get_sack(pkg);
1050     GPtrArray *advisorylist = g_ptr_array_new_with_free_func((GDestroyNotify) dnf_advisory_free);
1051     Solvable *s = get_solvable(pkg);
1052 
1053     dataiterator_init(&di, pool, 0, 0, UPDATE_COLLECTION_NAME,
1054                       pool_id2str(pool, s->name), SEARCH_STRING);
1055     dataiterator_prepend_keyname(&di, UPDATE_COLLECTION);
1056     dataiterator_prepend_keyname(&di, UPDATE_COLLECTIONLIST);
1057     while (dataiterator_step(&di)) {
1058         dataiterator_setpos_parent(&di);
1059         if (pool_lookup_id(pool, SOLVID_POS, UPDATE_COLLECTION_ARCH) != s->arch)
1060             continue;
1061         evr = pool_lookup_id(pool, SOLVID_POS, UPDATE_COLLECTION_EVR);
1062         if (!evr)
1063             continue;
1064 
1065         cmp = pool_evrcmp(pool, evr, s->evr, EVRCMP_COMPARE);
1066         if ((cmp > 0 && (cmp_type & HY_GT)) ||
1067             (cmp < 0 && (cmp_type & HY_LT)) ||
1068             (cmp == 0 && (cmp_type & HY_EQ))) {
1069 
1070             // We need to move the di dataiterator to the start of the advisory collection
1071             // so that di_advisory_collection can be initialized with SOLVID_POS because
1072             // the collection it self doesn't have an id.
1073             dataiterator_seek(&di, DI_SEEK_PARENT);
1074             dataiterator_setpos_parent(&di);
1075             dataiterator_seek(&di, DI_SEEK_PARENT);
1076 
1077             bool isModuleCollectionApplicable = true;
1078             Dataiterator di_advisory_collection;
1079             dataiterator_init(&di_advisory_collection, pool, 0, SOLVID_POS, UPDATE_MODULE, 0, 0);
1080             while (dataiterator_step(&di_advisory_collection)) {
1081                 dataiterator_setpos(&di_advisory_collection);
1082                 Id name = pool_lookup_id(pool, SOLVID_POS, UPDATE_MODULE_NAME);
1083                 Id stream = pool_lookup_id(pool, SOLVID_POS, UPDATE_MODULE_STREAM);
1084                 Id version = pool_lookup_id(pool, SOLVID_POS, UPDATE_MODULE_VERSION);
1085                 Id context = pool_lookup_id(pool, SOLVID_POS, UPDATE_MODULE_CONTEXT);
1086                 Id arch = pool_lookup_id(pool, SOLVID_POS, UPDATE_MODULE_ARCH);
1087 
1088                 libdnf::AdvisoryModule moduleAdvisory(sack, di.solvid, name, stream, version, context, arch);
1089                 if (moduleAdvisory.isApplicable()) {
1090                     isModuleCollectionApplicable = true;
1091                     break;
1092                 } else {
1093                     isModuleCollectionApplicable = false;
1094                 }
1095             }
1096             dataiterator_free(&di_advisory_collection);
1097 
1098             if (isModuleCollectionApplicable) {
1099                 g_ptr_array_add(advisorylist, dnf_advisory_new(sack, di.solvid));
1100             }
1101 
1102             dataiterator_skip_solvable(&di);
1103         }
1104     }
1105     dataiterator_free(&di);
1106     return advisorylist;
1107 }
1108 
1109 /**
1110  * dnf_package_get_delta_from_evr:
1111  * @pkg: a #DnfPackage instance.
1112  * @from_evr: the EVR string of what's installed
1113  *
1114  * Gets the package delta for the package given an existing EVR.
1115  *
1116  * Returns: a #DnfPackageDelta, or %NULL
1117  *
1118  * Since: 0.7.0
1119  */
1120 DnfPackageDelta *
dnf_package_get_delta_from_evr(DnfPackage * pkg,const char * from_evr)1121 dnf_package_get_delta_from_evr(DnfPackage *pkg, const char *from_evr)
1122 {
1123     Pool *pool = dnf_package_get_pool(pkg);
1124     Solvable *s = get_solvable(pkg);
1125     DnfPackageDelta *delta = NULL;
1126     Dataiterator di;
1127     const char *name = dnf_package_get_name(pkg);
1128 
1129     dataiterator_init(&di, pool, s->repo, SOLVID_META, DELTA_PACKAGE_NAME, name,
1130                       SEARCH_STRING);
1131     dataiterator_prepend_keyname(&di, REPOSITORY_DELTAINFO);
1132     while (dataiterator_step(&di)) {
1133         dataiterator_setpos_parent(&di);
1134         if (pool_lookup_id(pool, SOLVID_POS, DELTA_PACKAGE_EVR) != s->evr ||
1135             pool_lookup_id(pool, SOLVID_POS, DELTA_PACKAGE_ARCH) != s->arch)
1136             continue;
1137         const char * base_evr = pool_id2str(pool, pool_lookup_id(pool, SOLVID_POS,
1138                                                                  DELTA_BASE_EVR));
1139         if (strcmp(base_evr, from_evr))
1140             continue;
1141 
1142         // we have the right delta info, set up DnfPackageDelta *and break out:
1143         delta = dnf_packagedelta_new(pool);
1144 
1145         break;
1146     }
1147     dataiterator_free(&di);
1148 
1149     return delta;
1150 }
1151